.NET框架下的自動內存管理
C#使用的自動內存管理,使用 開發 者從繁重的手工分配、釋放內存的操作解放出來。內存的自動管理是由垃圾回收器來執行。一個對象使用內存的生命周期是這樣的: 當對象被創建時,它便分配了一定的內存,當構造器中的代碼開始運行時,這個對象就“活”了。 當
C#使用的自動內存管理,使用
開發者從繁重的手工分配、釋放內存的操作解放出來。內存的自動管理是由垃圾回收器來執行。一個對象使用內存的生命周期是這樣的:
當對象被創建時,它便分配了一定的內存,當構造器中的代碼開始運行時,這個對象就“活”了。
當這個對象或者是它的任何一部分在可以預計的將來已經沒有任何作用時,這個對象將不會再使用,它就應當被銷毀。
一旦這個對象符合了對銷毀的條件,在一定的時間后,這個對象的銷毀器就將被執行,一般情況下,除非被顯示地重寫,這個銷毀器只能運行一次。
一旦銷毀器被運行,那么這個對象以及它任何一部分都不可能在以后的運行中使用,這甚至包括正在運行的銷毀器。這時這個對象將被認為是不可見的,它所占的資源將會被回收。
最后由垃圾回收器釋放這個對象所占的資源。
垃圾回收器控制著這些對象的使用信息并利用這些信息控制內存,比如內存哪里創建了一個新對象,什么時候重新創建對象以及什么時候將這個對象釋放。
像其它的語言一樣,C#假定確實存在這樣一個垃圾回收器,而且這個垃圾回收器可以管理很大范圍的內存。比如,C#并不要求銷毀器一事實上要執行,也不要求對象一旦無用則馬上回收。
當然垃圾回收器的行為也是可以被控制的,這個控制的方法來自于System.GC類。這個類可以請求回收、銷毀器運行等操作。
下面是一個例子。
class A { ~A() { Console.WriteLine("Destruct instance of A"); } } class B { object ref; public B(object o) { ref = o; } ~B() { Console.WriteLine("Destruct instance of B"); } } class TMest { static void Main() { B b = new B(new A()); b = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } |
上面的程序創建了類A與類B的一個實例,當變量b被賦于null值時,A與B均符合了垃圾回收器的回收要求。此時就沒有任何代碼能夠訪問它們了。
執行的結果,下面兩種情況都有可能:
Destruct instance of A Destruct instance of B 與
Destruct instance of B Destruct instance of A |
因為上面的程序的并沒有限制這兩個對象被回收的順序。
在某些敏感的條件下,有關區分“銷毀”與“回收”操作條件的定義是非常重要的:
class A { ~A() { Console.WriteLine("Destruct instance of A"); } public void F() { Console.WriteLine("A.F"); TMest.RefA = this; } } class B { public A Ref; ~B() { Console.WriteLine("Destruct instance of B"); Ref.F(); } } class TMest { public static A RefA; public static B RefB; static void Main() { RefB = new B(); RefA = new A(); RefB.Ref = RefA; RefB = null; RefA = null; // A and B now eligible for destruction GC.Collect(); GC.WaitForPendingFinalizers(); // B now eligible for collection, but A is not if (RefA != null) Console.WriteLine("RefA is not null"); } } |
在上面的程序中,如果垃圾回收器選擇先執行類B的銷毀器,那么執行的結果為:
Destruct instance of A Destruct instance of B A.F RefA is not null |
注意,雖然實例A并沒有被使用,但是從輸出的結果大家可以看到A的銷毀器確實執行了,而且連A的方法F也被執行了。同時我們也注意至,一個對象銷毀器的運行又可能使一個實例變得可用。在這種情況下,實例B銷毀器的執行使得先前并沒有調用的實例A也可以被訪問了,而這一種就是引用RefA的功勞,當調用WaitForPendingFinalizers方法以后,實例B就可以被垃圾回收器回收,而此時的實例A則還不可以。
為了區分這些行為,大家編寫程序時,最好只管理當前類的銷毀器,而不要采用引用其它類的實例或者靜態字段。
原文轉自:http://www.anti-gravitydesign.com
- 評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
-
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97
|