2011-06-21 232 views
1

近日,同時採取集中於面向對象編程的入門單位,我被介紹到C#中的垃圾收集器,而且它的作用是「清理」那些沒有對象更長時間被引用。然後我介紹了析構函數,以及在對象被刪除之前如何調用它們。對象實例化

當然,我想到了,但我從來沒有想過要問講師這件事;如果您在同一個類的析構函數中創建一個類的實例,會發生什麼?

C#示例

class Person{ 
~Person(){ 

    Person p = new Person(); 
    Console.WriteLine("Person destroyed"); 

} 
} 

class Program{ 
static void Main(string[] args){ 
    Person p = new Person(); 
} 
} 

我想從一個更理論的角度接近這一點,所以我不願意(在此階段)來嘗試它,因爲我可能會看不明白,但我有一些理論。此外,我現在不在普通計算機上;)

  • Person。〜Person()將會遞歸,因爲每次創建新Person時,都會調用它的析構函數並創建一個新的無限的人,或直到某種內存相關的異常發生。隨後,主將永不終止。
  • 編譯器會抱怨(無論如何,將這個選項添加到每個場景似乎都是一個好主意)。
  • 不知怎的,某種「析構函數跳過」會發生。即。對象銷燬不會被順序調用,因此構造函數也不會。

現在的類似相關問題。如果垃圾收集器的作用是刪除不再被引用/需要的對象,那麼在沒有垃圾收集器的環境中如何處理像上面這樣的情況 - 比如C++?

回答

4

我想這裏沒有真正的奧祕。

它不會「遞歸」這樣 - 你只是夾持在託管堆中被立即取消引用一個新的對象;從而使其成爲垃圾收集的候選對象。

最終垃圾收集器會再來一輪,再次觸發操作等

那不是遞歸 - 更像是一個鏈條。但最終每個Person將從內存中刪除。

而且,一段時間後,垃圾收集器會向您發送電子郵件,抱怨你這樣做不公平。

至於C++,以及我的猜測是一個堆棧溢出,因爲建設/破壞發生的事情,然後,和一個非常生氣的電腦之後。

如果你的下一個邏輯思想是'運行時/語言不應該阻止這種情況發生?' - 沒有。有問題的語言或運行時間不會阻止你做一些否則會被視爲不明智的事情;它相信你,程序員,確保你沒有這樣做。

也就是說 - 在應用程序關閉的情況(在下面重新您的評論).NET運行時會採取行動出於自身利益,將最終停止處理這些終結制定關機。終結器是爲了您的利益,而不是運行時的。

+0

我很想知道這個簡單程序的執行過程是如何停止的?它顯然會開始鏈接終結器並輸出到控制檯。運行時如何殺死這個進程(正如我所知,正常的終止會運行終結器)。 – InBetween

+0

@InBetween - 如果是異常終止,則沒有問題。在合作關機中,如果.Net運行時發現應用程序沒有彈球,它將最終停止處理終結器並釋放所有內容。終結者對你的計劃同樣重要。使用更現代的Windows操作系統,一旦進程關閉,資源也將被釋放。 –

2

更有趣的一點是,一個對象實際上可以在終結器中使用resurrect itself

class Foo 
{ 
    static public List<Foo> ZombieFoos = new List<Foo>; 

    ~Foo() 
    { 
     ZombieFoos.Add(this); 

     // Now there is a reference to this instance again (in the list).. 
     // The GC will not reclaim this instance.. huzzah we have been resurrected!! 
    } 
} 

甚至沒有遠程推薦...

+1

令人敬畏的方式造成麻煩! –

+1

我不知道C#的情況,但在Java中這是危險的,可能會讓人困惑,對象將會復活,但它的屬性會改變。特別是,終結器只在每個對象上調用一次,這意味着對象會回來一次,但它不會重複地這樣做,這可能會令人驚訝(好像,令人驚訝的是從對象返回的對象死在第一位......)。你可以閱讀這篇文章中的Java案例[Object Finalization and cleanup](http://www.javaworld.com/javaworld/jw-06-1998/jw-06-techniques.html) –

+1

@DavidRodríguez - dribeas相同在C#中是真實的,你將不得不手動重新註冊對象來完成。但是和Java一樣,這是危險的,*在C#中肯定會令人困惑,我只提到它,因爲它是殭屍對象!或者耶穌班,無論你想叫什麼:) – MattDavey

1

你可以,事實上,造成系統是99.9時間GC。只需通過每個Person對象獲取足夠的內存以便GC觸發堆0集合。