2013-12-19 98 views
1

为什么此代码在i = 690864192上抛出OutOfMemoryException?StringBuilder的最大容量

StringBuilder sb = new StringBuilder(); 
       for (int i = 0; i < Int32.MaxValue; i++) 
       { 
        sb.Append("s"); 
       } 
       Console.WriteLine(sb.ToString()); 
       Console.Read(); 

默认容量为16个字符,但这种增长在它需要到最高是int.MaxValue = 2,147,483,647。那么,为什么当字符数是690,864,192,这比最大容量小得多,是否会抛出异常?

+7

'OutOfMemoryException'是自描述。 – Paulpro

+1

所以基本上我没有足够的内存来存储StringBuilder实例和那么多字符? –

+0

那时你分配了1.29GB的内存。这是一个巨大的块! – Harrison

回答

2

每次StringBuilder分配一个新的char[](通过指向以前chunk实例..这是另一个StringBuilder)..你把压力的疯狂量的垃圾收集器。

对象的大小有内存限制。在任何情况下,您的对象可能会在您达到最终结果前为您的应用程序分配最大内存量......因此OutOfMemoryException

最后一个StringBuilder实例指向最后一个实例,它在最大化之前指向最后一个实例......该实例在最大化之前也指向前一个实例...等等。您有一个GC根的巨大图形,得到清理。

19

所以基本上我没有足够的内存来存储一个StringBuilder实例与许多字符?

No no no no no。

RAM无关紧要;近20年来,RAM并不是相关的记忆量度! 虚拟地址空间是相关的措施。

令人惊讶的是,相信记忆仍然像80年代在DOS机器上那样工作的人数惊人。我的建议是了解现代操作系统如何处理内存。 RAM是性能优化。内存是页面文件

想想这样。你有一个可容纳一百万辆汽车(内存页)的停车场(页面文件)。你有一个车道(RAM),可以容纳十辆车。你有一个钥匙圈,可以容纳一千个密钥(虚拟内存)。你拥有一千辆汽车。你最常使用的十个在车道上。其他990在街上的停车场。

当您在车道上用完房间时,您只需将其中一辆车移动到停车场即可。 (RAM使访问经常使用的网页快。)

但是,当你买车#1001,你已经用完的资源是在钥匙圈空间,而不是房间在停车场房间车道。您随时可以在车道上留出更多空间,并且您在停车场有大量额外空间,但您的钥匙圈只有这么大。

为什么当字符数是690,864,192这比最大容量小得多,是否会抛出异常?

在32位Windows机器上,每个进程只能获得2 GB的用户可寻址虚拟地址空间。

在每个字符两个字节中,6.9亿字节是14亿字节,这是一个巨大的分数的2GB地址空间。你只剩下0.6 GB左右,以适应其他所有过程。在某些时候,字符串构建器将需要分配另一个块,并且在地址空间中的任何位置都没有可用的空闲块,因此分配失败。

你为什么试图做到这一点呢?一个14亿字节的字符串非常荒谬。

+0

我只是无聊,想要试验。我已经做了类似的继承。 –