2011-06-21 30 views
4

我已閱讀此文章:http://blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048149.aspx,說實話,我不明白每一個細節。據我所知,在下面的代碼中,即使我沒有將c設置爲null,也應該收集c。另一件事是,只要我們在同一個函數的範圍內,在foreach期間發生的分配似乎沒有被釋放。 (參見下面的示例)收集仍在範圍內的物體--GC.Collect

class Program 
{ 
    public class SomeClass 
    { 
     public byte[] X; 

     public SomeClass() 
     { 
      X = new byte[1024 * 1024 * 100]; 
      X[155] = 10; 
     } 
    } 

    static void Main() 
    { 
     Console.WriteLine("Memory: " + GC.GetTotalMemory(false)); 

     SomeClass c; 
     c = new SomeClass(); 

     Console.WriteLine("Memory: " + GC.GetTotalMemory(false)); 
     GC.Collect(); 
     Console.WriteLine("Memory: " + GC.GetTotalMemory(true)); 
     Console.ReadKey(); 

     /* 
     * Output: 
     * 
     * Memory: 186836 
     * Memory: 105044468 
     * Memory: 104963676 
     * 
     */ 
    } 
} 

EDIT用於第一實施例中的解決方案:在調試模式(在調試器不運行,但即使是彙編模式)。如果我使用Release,它將按預期工作:即使沒有設置爲null,也會收集到c。對於第二個例子,同樣適用。

第二示例

static void Main(string[] args) 
{ 
    Console.WriteLine("Startup Memory: " + GC.GetTotalMemory(false)); 

    var obj = BOObject.Get(); 

    Console.WriteLine("Fetched Object: " + GC.GetTotalMemory(false)); 
    GC.Collect(); 
    Console.WriteLine("Fetched Object (Collected): " + GC.GetTotalMemory(false)); 

    foreach (var node in obj.Traverse()) 
    { 
     string name = node.Name; 
    } 

    Console.WriteLine("Traversed: " + GC.GetTotalMemory(false)); 
    GC.Collect(); 
    Console.WriteLine("Traversed (collected): " + GC.GetTotalMemory(false)); 

    obj = null; 

    GC.Collect(); 
    Console.WriteLine("collected: " + GC.GetTotalMemory(true)); 
    Console.Read(); 
} 

輸出:

啓動存儲器:193060 擷取的:8972464 擷取的(累計):5594308 走過:272553096 遍歷(收集):269564660 收集:269564048

如果我把foreach循環放在另一個函數中,並調用這個函數,在.Col之後使用這個函數lect是調用約爲5800000.那麼,爲什麼當我在同一個函數中有foreach循環時垃圾不會被收集?

回答

6

在評論雷蒙德的文章和雲錦的MSDN文章here

其實,對於調試代碼,JIT 每一個變量的函數 端延伸一生提到。

因此,您收集的內容不會以調試模式收集,因爲您發現它以及爲什麼它將以發佈模式收集。

0

garbace收藏家的行爲是不確定的,不應該被認爲是確定性的。不要依賴GC。

你在問爲什麼GC 不是在給定的時間點收集垃圾。更好的問題將是爲什麼它在給定的時間點收集

+0

http://msdn.microsoft.com/en-us/library/xe0c2357.aspx 這不是確定性的,但可以強制收集未收集到的對象。 GC.GetTotalMemory(true)等待當前集合完成。所以至少應該釋放一些數據。這不會是每次嘗試相同的金額是可以的,但不會有200 MB的差異... – SACO

+1

@Malone它不是確定性的。所以短語「所以至少應該釋放一些數據」並不適用。爲了能夠說它必須是確定性的。 – Rangoric