【问题标题】:When OutOfMemoryException occurs?何时发生 OutOfMemoryException?
【发布时间】:2017-04-20 18:16:03
【问题描述】:

考虑这段代码:

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

当我们运行该代码时,会发生 OutOfMemoryException。Physical memory 在 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 位模式下运行它。

【问题讨论】:

  • 当涉及到内存不足错误时,物理内存几乎是无关紧要的。您可能想阅读It's the address space, stupid
  • 字符串不能超过 2^30 (1,073,741,824) 个字符,因为 Microsoft CLR(公共语言运行时)规定了 2GB 的限制。
  • 小知识:那个for循环坏了,100000000000大于int.MaxValue,需要用long来代替。

标签: c# memory-management


【解决方案1】:

.NET 中对象的最大大小为 2 GB,即使在 64 位系统上启用了gcAllowVeryLargeObjectsgcAllowVeryLargeObjects 上的文档显示为 字符串和其他非数组对象的最大大小不变.,我猜是因为它的实现方式)。

这意味着你只能分配一个大小为 2GB 的字符串。由于sizeof(char) 为 2,并且类本身有一点开销,因此您可以设置的最大大小为 int.MaxValue / 2 - 32

【讨论】:

    【解决方案2】:

    您的第一个示例需要 1 个 int.MaxValue * 2 个 连续 内存。您的第二个示例需要 100000000000 100 字节 * 2 的连续内存。

    .NET 就是找不到一个足够大的块来将其全部放入一个空间中。

    对象大小也有 2GB 的硬限制。在 64 位平台上,您可以使用 gcAllowVeryLargeObjects 使其更大,但该设置仅影响数组,不会影响字符串的限制。

    【讨论】:

    • .NET 甚至不会搜索那么多空间。对象大小有 2GB 的限制,即使在 x64 下也是如此(启用该选项的数组除外)
    • 其实这个答案的第一部分(直到2GB硬限制)与问题无关,因为作者在64位模式下运行,找到连续的4GB块应该没有问题。
    • @Damien_The_Unbeliever 您可以在应用程序设置中启用大型对象。请参阅:stackoverflow.com/questions/13520956/… - 那么大于 2GB 的对象应该是可能的 - 不是吗?
    • @TripleEEE 不,请阅读我在回答中链接到的文档。它特别说它不适用于字符串。
    • @ScottChamberlain 感谢您的建议-我只是错过了此评论-很高兴知道-谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多