簡體   English   中英

ASP.NET:在某些情況下我應該擔心內存泄漏嗎? [C#]

[英]ASP.NET: Should I be worried about memory leaks in certain situations? [C#]

在兩個對象相互引用的情況下,我關注垃圾收集......

public class A
{   public readonly B _b;
    public A()
    {   _b = new B(this);
    }
}

public class B
{   public readonly A _a;
    public B(A objA)
    {   _a = objA;
    }
}

在這種情況下,第三類可以引用A ...

public class Foo
{   public A _a = new A(); // A and B are both created here.
    public void Bar()
    {   _a = new A();
    }   // Create a new A (and B)
}

通常,垃圾收集器會處理不再具有任何活動引用的對象。 但在這種情況下,A和B對象永遠不會丟失所有活動引用,因為它們總是相互引用。

Foo對象用新的A (和B )替換當前的A (和B )時,垃圾收集器是否能夠清除舊的A (和B )而不用循環對象引用啟動無限循環?

這是一個嚴重的問題,因為它是一個ASP.NET應用程序。 這些對象將在每個Web請求中多次創建,並且如果垃圾收集器無法清除它們,則可能會延遲服務器重新啟動。
可能的負面結果:
<<由於RAM溢出,Web服務器崩潰。
<< Webserver因無限垃圾收集循環而崩潰。

在這種情況下,.NET如何處理垃圾收集?

.NET GC通過跟蹤有根引用來工作,例如靜態字段和范圍內局部變量。 它正確處理參考周期。 例如,如果A < - > B,但都沒有從有根參考引用,則會收集它。

讓我們考慮GC如何確定它何時可以回收內存。 當CLR嘗試分配內存並且內存不足時,它會執行垃圾回收。 GC枚舉所有有根引用,包括任何線程調用堆棧上的靜態字段和范圍內局部變量。 它將這些引用標記為可訪問,並遵循這些對象包含的任何引用,並將它們標記為可訪問。 它繼續此過程,直到它訪問了所有可訪問的引用。 任何未標記的對象都是不可訪問的,因此是垃圾。 GC壓縮托管堆,整理引用以指向它們在堆中的新位置,並將控制權返回給CLR。 如果釋放了足夠的內存,則使用此釋放的內存繼續分配。 如果不是,則從操作系統請求額外的內存。

- 來自http://msdn.microsoft.com/en-us/magazine/cc163491.aspx

如果A - > B,B - > A並且沒有對A和B的其他引用,則GC足夠智能以釋放這些對象。

在ASP.NET中,增加了應用程序池的保險。 應用程序的許多實例保存在內存中,並根據需要分配給各種會話。 有時,即使在會話的上下文中,IIS也會決定刷新應用程序池的好時機。 當會話結束時,IIS通常會關閉並重新啟動應用程序,如果它與每個應用程序,每個池或整個系統內存限制相沖突。 有時這甚至發生在會話中間; 這在SOA中很常見,其中外部Web層通過WCF與另一個服務器通信,並且服務層可以在Web層的調用之間刷新。

.NET Garbage收集器可以毫無問題地清除循環引用。

它不計算對舊VB6 GC等對象的引用。
它通過從特殊的“對象根”開始遍歷內存中的所有對象來跟蹤活動對象。

更簡單地說:

當垃圾收集器運行時,它從內存寄存器和靜態字段等開始。 這些被稱為“根”。

從那里,垃圾收集器跟隨從根到其他對象實例的引用。 這將創建從根可到達的所有對象的圖形。

如果您的對象無法從根目錄訪問,那么它們將被視為未引用,並且可以由垃圾收集器清理。

暫無
暫無

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

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