2011-06-15 71 views
4

我讀了一些關於垃圾收集的信息(它是如何工作等)。我試着理解它是如何工作的,但我認爲我有問題。我知道垃圾收集器運行時:
是不夠內存,
你調用GC.Collect()。
這是我的代碼:垃圾收集器C#,關於'清除'對象的問題

public partial class Form1 : Form 
{ 
    public Testing _d; 
    public Boolean _first = false; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if (!_first) 
     { 
      _d = new Testing(); 
      int test = _d.DoSomething("example"); 
     } 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     _first = true; 
    } 

    private void button3_Click(object sender, EventArgs e) 
    { 
     //if (_first) 
     //{ 
     // _d = null; 
     //} 
     GC.Collect(); 
    } 
} 

public class Testing 
{ 
    private ASCIIEncoding _ascii; 
    private bool _disposed = false; 

    public Testing() 
    { 
     _ascii = new ASCIIEncoding(); 
    } 

    public int DoSomething(string message) 
    { 
     return _ascii.GetByteCount(message); 
    } 
} 

當我點擊按鈕1,我在創建新的對象測試。 _d是對這個新對象的引用。我正在使用JetBrains dotTrace Memory轉儲內存,並看到這個新對象存在。點擊button2後,我將布爾_first設置爲true,以使_d變得無法訪問。在這一點上,我想當我運行GC.Collect()GC將從堆棧'清除'這個對象,但我看到它仍然存在。我誤解了GC的工作?或者我做錯了?
它在我設置時工作_d = null;

+0

你想在這裏解決什麼問題?你有實際的分析數據表明你的應用程序有內存泄漏嗎? – 2011-06-15 15:21:55

回答

3

設置first=false不作根據GC,_d實例無法訪問。邏輯上,您可能永遠不會再使用它,但它仍然在Form1類中引用。

如果有人再次設置first=true,你會不會期望對象仍然可用?

8

點擊Button2不會使_d無法訪問。

GC僅收集未被根目標對象引用的對象。
只要您的表格參考_d,它將不會被收集。

+0

迂腐/明顯的注意:即使表單有一個引用'_d',如果表單本身不可訪問,也可以收集'_d'。 – Brian 2011-06-15 17:55:18

4

這是因爲_d是您設置並且從不清除的Testing實例的參考。 _d仍然指向堆上的對象,直到您清除它(通過調用(_d = null)將保持這一參考。

無法訪問並不意味着_d不能被分配到別的東西,而是對象坐在堆沒有被稱爲機會再次(在代碼中不存在引用)

因此,GC不可能清除它,因爲它可能仍然在你的代碼中使用以後。

+0

這意味着我不應該擔心它,或者我應該設置爲空? – damned 2011-06-15 17:03:30

+0

我通常不會擔心;一旦表單本身無法訪問,它仍然是可收集的。如果'Testing'非常大*並且*表單很可能會在'button3_Click'之後停留,而沒有'_d'後來被重新分配,那麼可以將'_d'空置爲一個好主意。 – Brian 2011-06-15 18:04:30

3

您誤會了GC如何確定某個對象是否可訪問:當前本地作用域中的某個變量所引用的任何對象,任何可訪問的對象的靜態變量和任何實例變量本身都是「可訪問的」 - 將它看作一個圖表,將前面提到的變量作爲圖的「根」。

在你的例子中,_d仍然持有對你的對象的引用,所以它仍然可以訪問,不會被垃圾回收。

0

如果你要調用GC.Collect(),所有對象,無論它們在內存中存在多久,都被考慮用於收集;但是,託管代碼中引用的對象不由GC收集。檢查this