【发布时间】:2015-08-02 09:07:26
【问题描述】:
有很多关于 .NET LOH 的信息,并且已经在各种文章中进行了解释。但是,有些文章似乎缺乏一点精确性。
过时的信息
在Brian Rasmussen's answer (2009), program manager at Microsoft 中,他说限制是 85000 字节。他还告诉我们,还有一个更奇怪的例子,double[],大小为 1000 个元素。 Maoni Stephens (MSDN, 2008), member of the CLR team 规定了相同的 85000 限制。
在 cmets 中,Brian Rasmussen 变得更加精确,让我们知道它可以用 85000 字节 - 12 字节的 byte[] 重现。
2013 年更新
Mario Hewardt (author of 'Advanced Windows Debugging') 在 2013 年告诉我们,.NET 4.5.1 现在也可以压缩 LOH,如果我们告诉它这样做的话。由于默认情况下它是关闭的,除非您已经意识到,否则问题仍然存在。
2015 年更新
我无法再重现 byte[] 示例。使用简短的蛮力算法,我发现我必须减去 24(SOH 中的byte[84999-24],LOH 中的byte[85000-24]):
static void Main(string[] args)
{
int diff = 0;
int generation = 3;
while (generation > 0)
{
diff++;
byte[] large = new byte[85000-diff];
generation = GC.GetGeneration(large);
}
Console.WriteLine(diff);
}
我也无法重现 double[] 语句。暴力破解给了我 10622 个元素作为边界(SOH 中的double[10621],LOH 中的double[10622]):
static void Main(string[] args)
{
int size = 85000;
int step = 85000/2;
while (step>0)
{
double[] d = new double[size];
int generation = GC.GetGeneration(d);
size += (generation>0)?-step:step;
step /= 2;
}
Console.WriteLine(size);
}
即使我为较旧的 .NET 框架编译应用程序,也会发生这种情况。它也不依赖于 Release 或 Debug 构建。
如何解释这些变化?
【问题讨论】:
-
感谢您发布更新。问题真的不在于您不能再复制
byte[85000-12]。 32 位进程仍然具有我描述的行为,您可以在最新的 CLR 上验证这一点。但是,正如您在下面指出的那样,差异是由于 64 位平台上的参考大小造成的,因此要复制 64 位,您需要考虑参考的不同大小,就像您在答案中显示的那样。
标签: c# .net debugging out-of-memory windbg