当发生 OutOfMemoryException 异常时?

3

考虑以下代码:

string value = new string('a', int.MaxValue);

当我们运行该代码时,会出现OutOfMemoryException异常。Windows 8物理内存限制为128 GB。

那么为什么.Net会为该代码抛出OutOfMemoryException呢?

此外,该代码永远不会抛出OutOfMemoryException:

List<string> list = new List<string>();
for (int i = 0; i < 100000000000; i++)
{
    list.Add(new string('a', 100 ));
}

我在64位模式下运行它。


5
当涉及到内存不足错误时,物理内存几乎无关紧要。你可能想阅读《傻瓜,这是地址空间的问题》(英文原文链接在文中)。 - Damien_The_Unbeliever
4
由于Microsoft CLR(公共语言运行时)实施了2GB的限制,因此字符串不能超过2^30(1,073,741,824)个字符。请注意,这里不会进行任何解释或额外内容的返回。 - Leonid Malyshev
5
小贴士:那个for循环有问题,100000000000大于“int.MaxValue”,你需要使用long来代替。 - Şafak Gür
2个回答


4
你的第一个示例需要 1 个 int.MaxValue * 2 的连续内存。第二个示例需要 100000000000 个 100 字节 * 2 的连续内存。
.NET 无法找到足够大的单块内存来容纳所有内容。
对象大小也有 2GB 的硬限制。在 64 位平台上,你可以使用 gcAllowVeryLargeObjects 来增加这个限制,但该设置仅影响数组,不会影响字符串的限制。

3
.NET不会搜索那么大的空间。即使在x64下(除非启用了该选项),对象大小的限制为2GB,数组除外。 - Damien_The_Unbeliever
2
实际上,这个答案的第一部分(直到2GB硬限制)与问题无关,因为作者在64位模式下运行,在那里找到连续的4GB块不应该是一个问题。 - Evk
@Damien_The_Unbeliever,您可以在应用程序设置中启用大对象。请参见:https://dev59.com/WGYr5IYBdhLWcg3wn7kc - 然后大于2GB的对象应该是可能的,不是吗? - TripleEEE
2
@TripleEEE 不,去阅读我在答案中提供的文档。它明确说明它不适用于字符串。 - Scott Chamberlain
@ScottChamberlain 谢谢您的建议 - 我刚刚错过了这个备注 - 很好知道 - 谢谢 :) - TripleEEE
第二个例子的部分是不正确的。该列表存储对字符串实例的引用,而引用在32位系统上为4字节,在64位系统上为8字节。因此,列表需要的顺序内存是100000000000 * IntPtr.Size字节,而不是100000000000 100 byte * 2 - Şafak Gür

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接