2012-02-19 29 views
3

我一直在跟蹤海量應用程序中的大量內存泄漏,看起來問題在於MemoryStream類。無論何時我使用「使用」關鍵字或明確的關閉/處理,內存將永遠不會被垃圾收集器收集。這裏有什麼問題?C#MemoryStream泄漏內存,處理/關閉/ etc後?

byte[] bData = System.IO.File.ReadAllBytes("F:\\application_exit_bw.png"); 
using(System.IO.MemoryStream hMemoryStreamOutput = new System.IO.MemoryStream()) 
{ 
    for (int i = 0; i < 10000; i++) hMemoryStreamOutput.Write(bData, 0, bData.Length); 
} 
Thread.Sleep(Timeout.Infinite); 

使用明確的close/dipose行爲保持不變。內存被佔用,並保持這種狀態,直到我關閉我的應用程序,或者,應用程序填滿了所有的系統內存。幫幫我?

回答

1

問題的另一面是您正在使用,以確定「內存泄漏」的東西。有測量許多不同的方式「免費」的記憶,並根據它,你可能會得到tottaly不同的結果,在任務管理器

  • 內存使用展示 - 不可能往下走,即使所有的記憶被認爲是‘自由’的CLR GC由於道路GC使用內存
  • GC內存性能計數器(和財產) - 。這些的居然會顯示GC對內存視圖你想用它來檢測管理內存泄漏

有MemoryStream(和任何其他大型86K +)分配還有一件事 - 它們使用大對象堆,只能在完整G C,要觸發它,您可能需要運行GC.Collect兩次。在正常的應用程序流程中,它會發生足夠的變化,因此在應用程序關閉之前您可能看不到此內存已釋放。診斷 - 檢查GC採集性能計數器(GC數量)。

還有一:如果你正在試圖解決內存泄漏,因爲你得到「內存不足」異常可以通過地址空間碎片引起的(通常僅適用於32位進程)。如果是這種情況 - 考慮創建自己的內存流,該內存流不會在單個塊中分配內存,然後在增長流時不得不復制它。或者至少嘗試預先分配流中的空間。

4

這是一個非確定性GC的症狀。關於何時釋放內存,GC不會保證任何。這是正常的,預期的和想要的行爲。

嘗試調用GC.Collect的(),看是否能解決您的問題。另外,您需要以釋放模式運行,因爲在調試模式下,JIT將局部變量的生存期延長到方法的末尾,即使它們在某點之後未被使用。

+2

+1的調試模式尖,感謝 – 2012-02-19 00:22:50

+0

請告訴我downvote呢?有什麼不準確的地方?請報告錯誤,我會修復! – usr 2012-02-19 00:26:57

7

沒有什麼毛病MemoryStream類或示例代碼中的用法。 .Net中的GC不再立即清除內存。相反,當堆中的可用空間達到某個閾值或通過GC.Collect調用顯式調用它時,它會回收它。

在這種情況下,內存將被釋放的唯一方法是GC在using聲明之後和Thread.Sleep調用之前立即發生。這是相當不可能發生的,因此,如果您評測的程序,將有內存泄漏的外觀時,它實際上沒有泄漏

0

我已經使用這種方法進行批量處理

static byte[] buffer; 

    public static object Read(XmlDocument xmlDocument) 
    { 
     if (buffer == null) 
     { 
      buffer = new byte[1024 * 1024 * 512]; 
     } 

     if (xmlDocument != null) 
     { 
      using (MemoryStream ms = new MemoryStream(buffer)) 
      { 
       xmlDocument.Save(ms); 
       ms.Flush(); 
       ms.Seek(0, SeekOrigin.Begin); 

       object result = ReadFromStream(ms); 

       ms.Close(); 
       return result; 
      } 
     } 
     else 
     { 
      return null; 
     } 
    } 
0
調用

所以GC.Collect()是不是一個好的做法,並且不應該被用作溶液。

你可以試試,看看有沒有改變任何東西,但不依賴於故意GC.Collect的()調用...