2013-12-19 129 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

我只是無聊,想要試驗。我已經做了類似的繼承。 –