我有一个简单的值类型,它包装在堆栈上分配的缓冲区:
unsafe struct Value
{
// public fixed byte Data[1073741800]; // StackOverflow (2^30 - 24)
// public fixed byte Data[1073741801]; // InvalidProgram
// public fixed byte Data[2147483631]; // InvalidProgram
// public fixed byte Data[2147483632]; //OutOfMemory (2^31 - 16)
public fixed byte Data[2147483647]; // OutOfMemory
}
这样使用:
unsafe static void Main(string[] args)
{
Value value;
value.Data[0] = 0;
}
如果缓冲区太大,则可能发生堆栈溢出,这是意料之中的。
但是根据缓冲区的大小,CLR 的行为会有所不同:
对于高达 1073741800 (2^30 - 24)的大小,它会抛出StackOverflowException
对于[1073741801, 2147483631] 范围内的大小,它会抛出InvalidProgramException
对于[2147483632 (2^31 - 16), 2147483647] 范围内的大小,它会抛出OutOfMemoryException
如果重要的话,那就是发布 x86 版本。
它在运行时是一致的:与 .Net 2.0 和 .Net 4.5 的行为相同,所以看起来这不是一个错误。
为什么会有这种不同的行为?
它是否记录在某处?
感谢您的任何指示。
编辑
我用Mono 3.2.3进行了测试,行为相似,即存在三个级别的错误:SO -> IP -> OOM,但阈值不一样。
我不知道 Mono 团队现在如何开发它的实现,如果它完全独立于它是否从 MS 实现“复制粘贴”。
在第一种情况下,这意味着必须在某处指定此行为,因为两个独立工作的不同团队产生相同的奇怪行为实在是太巧合了,因此他们必须遵循相同的规范。
在第二种情况下,他们可能只是在 MS 实现中引入了一个小故障......
可以从任何团队中获得一些反馈。
如果这里没有反馈,我会发布一些 MS 和 Mono 的票。