簡體   English   中英

在.NET等托管環境中是否可能發生內存泄漏?

[英]Are memory leaks possible in managed environments like .NET?

在C ++中,很容易產生永久性內存泄漏 - 只需分配內存而不釋放內存:

new char; //permanent memory leak guaranteed

並且該內存在堆的生命周期內保持分配(通常與程序運行時的持續時間相同)。

在C#程序中,是否可能(在內存管理機制正常工作的情況下會導致特定的未引用對象被釋放)?

我仔細閱讀了這個問題並給出了答案,它提到了一些導致內存消耗高於預期的情況或IMO相當極端的情況,比如終結器線程死鎖,但是在正常運行的C#程序中會形成永久性泄漏內存管理?

這取決於您如何定義內存泄漏。 在非托管語言中,我們通常將內存泄漏視為已分配內存的情況,並且不存在對它的引用,因此我們無法釋放它。

在.NET中創建這種泄漏幾乎是不可能的(除非你調用非托管代碼,或者除非運行時有錯誤)。

但是,你可以得到泄漏的另一種“弱”的形式:當對內存的引用存在的(所以還是有可能找到並重新設置參考,允許GC來釋放正常的內存),但你認為它沒” t,所以你假設被引用的對象會得到GC。 這很容易導致內存消耗的無限增長,因為你正在堆積對不再使用的對象的引用,但是它們不能被垃圾收集,因為它們仍然在應用程序的某處被引用。

因此,在.NET中通常被認為是內存泄漏的情況只是您忘記了對對象的引用(例如,因為您未能取消訂閱事件)。 但是參考文獻存在,如果你記得它,你可以清除它,泄漏就會消失。

如果你願意,你可以在.NET中編寫非托管代碼,你用不安全的關鍵字包含你的代碼塊,所以如果你正在編寫不安全的代碼,你是不是回到自己管理內存的問題,如果沒有內存泄漏?

這不是一個內存泄漏,但如果你直接與硬件驅動程序通信(即不通過一組驅動程序的正確編寫.net擴展),那么很可能將硬件置於一個狀態,盡管可能或者可能不是代碼中的實際內存泄漏,您無法再重新啟動硬件或PC而無法訪問硬件...

不確定這是否是對你的問題有用的答案,但我覺得值得一提。

當對引用的分析顯示內存不可達時,GC通常會將無法訪問的內存的收集延遲到以后的某個時間。 (在某些受限制的情況下,編譯器可能會幫助GC並警告它在內存區域變為無法訪問時。)

根據GC算法,一旦運行收集周期就會檢測到無法訪問的內存,或者它可能在一定數量的收集周期內未被檢測到(例如,分代GC顯示此行為)。 有些技術甚至有從未收集的盲點(例如使用引用計數指針) - 有些人否認它們是GC算法的名稱,它們可能不適用於通用上下文。

證明將回收特定區域取決於算法和內存分配模式。 對於像標記和掃描這樣的簡單算法,很容易給出一個約束(直到下一個收集周期),對於更復雜的算法,問題更復雜(在使用動態數代的方案下,條件是完全收集對於不熟悉算法細節和使用的精確啟發式的人沒有意義

一個簡單的答案是經典的內存泄漏在GC環境中是不可能的,因為經典的內存泄漏被泄露,因為作為一個未引用的塊,軟件無法找到它來清理它。

另一方面,內存泄漏是程序的內存使用量無限增長的任何情況。 在分析軟件作為服務運行時可能會失敗的情況時(定義服務運行,可能一次持續數月),此定義非常有用。

因此,任何可持續保留對不需要的對象的引用的可擴展數據結構都可能導致服務軟件因地址空間耗盡而有效地失敗。

最簡單的內存泄漏:

public static class StaticStuff
{
    public static event Action SomeStaticEvent;
}

public class Listener
{
   public Listener() {
      StaticStuff.SomeStaticEvent+=DoSomething;
   }
   void DoSomething() {}
}

永遠不會收集監聽器的實例。

如果我們將內存泄漏定義為可以用於創建對象的內存,不能使用的內存或者可以釋放的內存那么

內存泄漏可能發生在:

  • WPF中需要使用弱事件的事件。 這尤其可以在附加屬性中發生。
  • 大物件

大對象堆碎片

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

暫無
暫無

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

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