2012-01-25 186 views
0

我對編寫代碼的正確方式感到有點困惑。我讀過,我不必在變量中保持引用,因爲垃圾收集不會清除它,但我不明白幾件事情。內存泄漏問題.net

  1. 這個怎麼樣代碼:

    private List<String> foo; 
    
    public List<String> bar() 
    { 
        foo = new List<String>(); 
        foo.add(something); 
        return foo; 
    } 
    

每次我打電話吧方法富列表失去了參考,這將是對垃圾收集的候選人呢?我應該聲明(並初始化?)大部分變量在類的開始處使用,或者在聲明之前使用或聲明並初始化該方法?

2. 處置對象怎麼樣?如果如果我有使用導航事件20 WebBrowser對象我寫這篇文章的代碼

private void browser_navigating(Object sender, NavigatingEventargs e) 
{ 
    Uri someurl = new URI(something); 
    List<String> somelist = new List<String>(); 
} 

,他們創造烏里和列表時,導航事件被解僱嗎?但是當我處理webBrowser時事件內部發生了什麼事?他們會失去參考?當我處置一些適用於他所有孩子的東西時,但它是否也適用於那些不實施iDisposable的對象(如Uri和List),以便他們從垃圾清除,還是留在內存中?

2.1。這些事件在註冊它的對象被丟棄後自動取消註冊?

3)我讀了靜態對象是內存泄漏的問題。 如果我需要多次使用一個類,我應該每次創建它,我需要聲明它是靜態的(例如,在我的情況下,我有一個靜態連接類,裏面有方法來登錄和與Web服務器交流,我聲明靜態(在我的mainWinform類)因爲我在它裏面存儲從登錄接收的cookie)

我會感謝你誰可以回答我的問題。

回答

1

1的其餘部分:我應該聲明(並初始化????)在類和使用最開始的變量的在方法裏面還是之前聲明和初始化?

通常情況下,一個對象應該在您完成這個任務時超出範圍。所以,如果它只是被一個方法內部使用,它應該是局部的方法。對象住的時間越長,就越有可能被提升到更高的一代堆上。上一代的數據收集成本較高,而且收集的次數要少得多。因此,越來越超出範圍的對象儘快一般會降低你的內存消耗也讓你的程序運行得更快。

2:但是,當我處理webBrowser時事件內部的對象發生了什麼?他們會失去參考?當我處置一些適用於他所有孩子的東西時,但它是否也適用於那些不實施iDisposable的對象(如Uri和List),以便他們從垃圾清除,還是留在內存中?

當你處理一個對象時,它實際上對世界是死的。別人誰擁有對它的引用仍然有參考,但對象將(或應,反正),如果他們試圖用它做任何事情引發ObjectDisposedException。時,它的設置

一個對象的非託管資源(文件句柄,連接等)被立即釋放。它的非託管資源通常由垃圾收集器清理。所以直到最後引用該對象超出範圍,他們將不被清理。

3)我讀了靜態對象是內存泄漏的問題。

這是因爲類的靜態字段永遠不會超出範圍。因此,除非您明確將其引用設置爲null或將其替換爲其他內容,否則無法清除它們引用的任何數據。

分別處理每個與Web服務器的會話要好得多。這不僅有助於垃圾收集器在您之後進行清理,還可以讓您執行諸如具有多個併發會話的事情。

0

每次我稱之爲bar方法的舊foo列表失去引用,它將成爲垃圾收集的候選者?

這可能是對的。分配foo = new List<String>導致foo停止指向之前的List<string>值。如果foo只有該對象的引用,那麼它將可用於收集。然而,如果你的類型中的另一個函數暴露了對象,那麼它可能仍然活着。例如

List<string> GetFoo() { 
    return foo; 
} 

我讀靜態對象是一個問題,內存泄漏

這部分是真實的。當一個對象引用被一個GC根保持不再被主動使用時,.NET中會發生內存泄漏。靜態字段是一個GC Root和一個麻煩的方式,因爲它不會像局部變量那樣消失。一個靜態字段實質上永遠保存着一個對象在內存中

class Holder { 
    public static List<string> StaticField; 
} 

Holder.StaticField = GetFoo(); 

原本存儲在fooList<string>現在由StaticField引用。直到StaticField指向另一個目的它將保持List<string>在內存中的程序