.NET OutOfMemoryException

ksm*_*ksm 12 .net c# out-of-memory

为什么这样:

class OutOfMemoryTest02
{
    static void Main()
    {
        string value = new string('a', int.MaxValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出异常; 但这不会:

class OutOfMemoryTest
{
    private static void Main()
    {
        Int64 i = 0;
        ArrayList l = new ArrayList();
        while (true)
        {
            l.Add(new String('c', 1024));

            i++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有什么不同?

Ste*_*end 10

你有没有看过int.MaxValue文档?它相当于2GB,这可能比你用于连续的"a"字符块的RAM要多 - 这就是你在这里要求的.

http://msdn.microsoft.com/en-us/library/system.int32.maxvalue.aspx

你的无限循环最终会导致相同的异常(或者与过度使用RAM间接相关的另一个异常),但这需要一段时间.尝试增加102410 * 1024 * 1024在循环情况下更快地重现症状.

当我使用这个更大的字符串大小运行时,我在68次循环(检查i)后的10秒内得到异常.


ulr*_*chb 7

您的

new string('a', int.MaxValue);
Run Code Online (Sandbox Code Playgroud)

抛出一个OutOfMemoryException简单因为.NET string有长度限制.MSDN文档中的"备注"部分说:

内存中String对象的最大大小为2 GB,即大约10亿个字符.

在我的系统(.NET 4.5 x64)new string('a', int.MaxValue/2 - 31)抛出,而new string('a', int.MaxValue/2 - 32)工作.

在第二个示例中,无限循环分配~2048个字节块,直到您的操作系统无法在虚拟地址空间中再分配任何块.当达到这个目标时,你也会得到一个OutOfMemoryException.

(~2048字节= 1024个字符*每个UTF-16代码点2个字节+字符串开销字节)

试试这篇伟大的Eric 文章.


Moo*_*ice 5

因为int.MaxValue是2,147,483,647,或者需要连续分配的2千兆字节.

在第二个示例中,OS每次只需要找到1024个字节进行分配,并且可以交换到硬盘驱动器.我相信如果你让它运行得足够长,你最终会在一个黑暗的地方:)