簡體   English   中英

C#大字節數組和內存泄漏如果沒有快速消除

[英]C# large byte array and memory leak if not nulled quickly

我有一個類,其字節數組從1,048,576字節到134,217,728字節。 在dispose void中,我將數組設置為null,調用dispose的方法在此之后調用GC.Collect

如果我立即處理,我將恢復記憶,但如果我等待10個小時並處理掉,內存使用量不會改變。

內存使用情況基於操作系統內存分配。 它可能會立即釋放,也可能不會。 這取決於操作系統的利用率,應用程序等。您可以在運行時釋放它,但這並不意味着操作系統總是將其恢復。 我不得不認為這是一種基於記憶模式(即這里的時間)的決定,這種決定影響了何時返回它的計算。 這是在這里解決的:

在c#中顯式釋放內存

注意:如果未釋放內存,則不會自動表示已使用。 它取決於CLR是否釋放了大量內存,但這種內存並沒有浪費。

也就是說,如果你想要技術解釋,你會想要閱讀關於大對象堆的文章: http//msdn.microsoft.com/en-us/magazine/cc534993.aspx

基本上,它是一個內存區域,分配了非常大的對象(超過85kB)。 它與其他記憶區域的不同之處在於它從未被壓縮,因此可能變得支離破碎。 我想你的情況會發生什么:

  • 情況1:您分配對象並立即調用GC.Collect。 對象在堆的末尾分配,然后釋放。 CLR在堆的末尾看到一個空閑段並將其釋放到操作系統。

  • 情況2:您分配對象並等待一段時間。 同時,在LOH中分配另一個對象。 現在,你的對象不再是最后一個了。 然后,當您調用GC.Collect時,您的對象將被刪除,但在內存段的末尾仍然存在其他對象。 因此CLR無法將內存釋放到操作系統。

基於我對.NET內存管理的了解,這只是一個猜測。 我可能完全錯了。

你的發現並不罕見,但並不意味着任何事情都是錯誤的。 為了收集,有些東西必須提示GC收集(通常是嘗試分配)。 因此,您可以構建一個消耗大量內存,釋放內存然后空閑的應用程序。 如果機器上沒有內存壓力,並且如果您的應用程序之后沒有嘗試執行任何操作,則GC將不會啟動(因為它不需要)。 一旦你忙,GC就會開始工作。 這種行為通常被誤認為是泄漏。

順便說一下:你是不是一次使用那個非常大的陣列? 如果是這樣,你最好還是保留它並重復使用它。 原因:大對象堆上分配了大於85,000字節的任何對象。 該堆僅在第2代集合中獲得GC'd。 因此,如果您經常分配和重新分配數組,那么您將會導致很多第2代(昂貴的)集合。

(注意:這並不意味着總是重用大型數組有一條硬性規則,但是如果你要對數組進行大量的分配/解除分配/分配,那么你應該測量一下,如果重復使用它會有多大幫助)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM