2009-11-14 60 views
3

我正在C#上工作。我想知道如何我可以釋放stringbuilder n字節[] ....因爲我使用字符串生成器時出現內存不足異常.... 另一件事是String.Replace()也給出了內存不足例外或有沒有其他方式做同樣的....請告訴我如何克服這些問題... 在此先感謝內存釋放字符串生成器在C#中的一個D字節[]:內存不足異常

+2

如果您在運行我們的內存時明確說明了您正在使用StringBuilder執行的操作,例如,在將StringBuilder轉換爲字符串時發生了什麼? – BillW 2009-11-14 08:23:09

+0

感謝您的回覆...當做的時候出現問題stringbuilder.Append() 也doin StringBulder.Replace(oldStr,newStr); – 2009-11-14 08:28:22

回答

4

你建立一個字符串有多大?你知道前面會有多大嗎?如果這樣設置StringBuilder的容量。

如果您不這樣做,它將以16的容量開始,然後每次突破該限制時將其翻倍。容量將變爲16,32,64,128。

每次它都這樣做時,它很可能需要重新分配內存。

如果數據很大,最好在文件流而不是StringBuilder中構建它?

5

如果您正在獲取OOM,您將保留太多數據。聽起來像你應該使用TextWriter(替換StringBuilder)或BinaryWriter/Stream(替換byte[]) - 特別是StreamWriterFileStream(寫入文件)。

例如:

using (TextWriter dest = File.CreateText("out.txt")) 
{ 
    for (int i = 0; i < 100000; i++) 
    { 
     dest.Write(i); 
     dest.Write(": "); 
     dest.WriteLine(i % 5000); // why not 
    } 
} 

這樣的基於流的API的優點是,一旦你寫數據塊可以被垃圾收集等

3

下面是一些代碼進行試驗用:我的機器上

using System; 
using System.Text; 

class Program { 
    static void Main(string[] args) { 
    StringBuilder sb = new StringBuilder(); 
    try { 
     //sb.Capacity = 690 * 1024 * 1024; 
     while (true) sb.Append("asdf"); 
    } 
    catch (OutOfMemoryException) { 
     Console.WriteLine("Died at: {0:N0} characters", sb.Capacity); 
     Console.WriteLine("Memory used: {0:N0} bytes", GC.GetTotalMemory(false)); 
     Console.ReadLine(); 
    } 
    } 
} 

輸出(Win7的32位):

Died at: 268,435,456 characters 
Memory used: 537,091,632 bytes 

32位操作系統提供了接近2千兆字節的虛擬內存的進程。正如你所看到的,示例程序遠遠沒有達到這個目標,只消耗了25%。問題是虛擬內存地址空間碎片。可用的2千兆字節需要存儲代碼和數據。您可以瞭解虛擬機如何與SysInternal的VMMap utility分離。

您可以通過一些關於StringBuilder如何工作的知識來做些事情。它使用內部數組來存儲字符串。根據需要重新分配此數組以存儲不斷增長的字符串,每次將字符大小加倍。 Capacity屬性告訴你該數組的大小。

這會導致另一種碎片,堆碎片。數組大小加倍後,可以收集舊數組,但會生成一個「空閒塊」,無法合併回來,從而無法用於大型連續分配。這是大對象堆和Windows堆管理器的實現細節,谷歌的「look-aside cache」來了解更多關於它的信息。

一種解決方法是在虛擬內存空間碎片化之前快速吞併虛擬內存空間。刪除評論,看看在工作中。在我的機器:

Died at: 723,517,440 characters 
Memory used: 1,447,256,944 bytes 

我通過實驗微調的容量值,您可能需要做同樣的使你的機器上工作。差異非常顯着,幾乎是3倍。請注意,這是不太可能在真實程序中很好地重現,時間安排至關重要。或者在另一臺機器上,請確保遠低於分界點。實際上,一旦您使用的緩衝區超過了1.34億個字符,您將面臨OOM風險。