2012-06-11 58 views
4

我是一名新程序員,我只想出一個內存泄漏的問題。如果我在一個循環中聲明一個變量以使其一次又一次被聲明,我是否在泄漏內存? 例如,我有我在循環中泄漏內存嗎?

while(true) 
{ 
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768); 
    //do something else 
} 

我知道這是一個無限循環,但我的問題是關於內存。內存使用量在這個循環中增長得快嗎?我應該手動釋放MyImage嗎?

+0

我會冒險猜測,並說是...但我不是100%確定,所以請不要把它當作福音。 – Richard

+0

@Killercam你確定嗎?因爲我聽到了不同的東西,我不知道。在這種情況下,或者一般來說,你的意思是說Image對象可以嗎? – YankeeWhiskey

回答

6

使用後需要撥打MyImage.Dispose()

另一種方式是將代碼更改爲:

while(true) 
{ 
    using(Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)){ 
     //do something else 
    } 
} 
+0

我意識到也許這個班不實施'IDisposable'。所以,如果它實現了IDisposable,或者它使用了實現IDisposable的某些東西,那麼應該採用它,在這種情況下,您應該實現它來處理內部對象。 – ivowiblo

+0

這只是爲了提高效率還是真正的內存泄漏? – YankeeWhiskey

+0

類型爲IDisposable的類通常使用在調用Dispose()方法之前不能釋放的內存。正如你可能在無限循環中使用它們一樣,它可能導致內存泄漏(我的意思是,如果你使用Disposable對象而不調用Dispose,它會導致內存泄漏) – ivowiblo

1

我是不是內存泄漏,如果我在一個循環中聲明一個變量,使其一再聲明?

不,你不這樣做,如其他人所說的問題可能是,如果圖像是包裝的Image對象

但對於你的問題,這是不申報在一個循環內的變量的問題,在每次迭代中爲其指定一個新值

1

有些情況下,緊密環路可能導致OOM問題。但是,Image實現了IDisposable,因此請務必通過using聲明對其進行調用,以便在完成後可以釋放資源。

using (Image<Gray, Byte> MyImage = new Image<Gray, Byte>(1024, 768)) 
{ 
    //do stuff 
} 

確保Image<T,U>工具IDisposable如果Image<T,U>實現所有管理對象。

1

在你的問題的一般形式中,你本身並沒有泄漏內存,但是你可能會增加你的內存佔用比GC更快的速度(取決於你正在使用的對象的確切行爲和內存佔用情況)。如果是這樣,這將會產生很多類似於內存泄漏的效果。

在您的具體示例中,Image對象包含非託管資源,其中可能包括內存(或文件句柄或GDI對象等)。正如其他答案所指出的那樣,如果你不處理,這些非託管資源將不會被回收(或者如果他們有終結器,則可以在GC的第二次回收中回收)。

3

垃圾收集器(GC)將爲您完成這項工作 - 最終。在你提出的例子中,你必須小心,因爲在這種情況下GC會嘗試和管理它花費在垃圾收集上的時間與應用程序內存消耗(工作集)的時間。因此,應用程序可能會消耗更多的內存,尤其是在您說明的情況下。

CLR完全自動處理這個內存,你永遠不會自己釋放託管內存。例如,考慮下面的

public void Test() 
{ 
    byte[] myArray = new Byte[1000]; 
    // ... 
} 

Test執行時,一個數組來保存1000個字節是在存儲器堆中分配。該數組由變量myArray引用,存儲在局部變量堆棧中。當這個方法退出時,這個局部變量會超出範圍,這意味着什麼都沒有留下來引用內存堆上的數組。然後,孤立數組有資格被GC回收。然而,這個集合可能不會立即發生,因爲CLR關於是否收集的決定是基於許多因素(可用內存,當前內存分配,自上次收集以來的時間等)。t這意味着,對於收集是否存在不確定的延遲垃圾回收之前所花費的時間。

鑑於上述情況,在您描述的情況下,在循環/包含方法期間內存消耗會大幅增加。這裏要好得多要麼使用一個using聲明

while (true) 
{ 
    using (Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768)) 
    { 
     // ... 
    } 
} 

或每個循環之後的Image調用對象的dispose()

while (true) 
{ 
    Image<Gray, Byte> MyImage = new Image<Gray, Byte> (1024, 768); 
    // ... 
    MyImage.Dispose(); 
} 

Asside:你可以隨時檢查這些內存消耗爲自己(使用System.Diagnostics程序)通過查詢性能計數器(測試你的流程的實際內存消耗):

string procName = Process.GetCurrentProcess().ProcessName; 
using (PerformanceCounter pc = new PerformanceCounter("Process", "Private Bytes", procName)) 
    Console.WriteLine(pc.NextValue()); 

注:讀取性能計數器需要管理員權限。