2011-11-19 66 views
12

這是我最近在採訪中被問到的一個問題:在'GC.Collect()'調用期間將收集哪些「隨機」對象?以下哪些對象符合垃圾回收的條件?

String a = new Random().Next(0, 1) ==1 ? "Whatever 1" : "Whatever 2"; 

String b = new WeakReference(new Random()).Target.Next(0, 1) == 1 ? 
    "Whatever 1" : "Whatever 2"; 

GC.Collect(); 

我回答說,這是具體實現的問題,它高度依賴於GC實施和相應的弱引用語義。據我所知,C#規範沒有提供GC.Collect應該做什麼的精確描述,以及弱引用應該如何處理。

但是,我的面試官想聽聽別的。

+3

你太客氣了。我的回答是,如果事情存在可怕的錯誤......如果'Java'標籤也被添加到這個問題中, –

+0

會很好。 – Bhushan

回答

13

兩個Random()實例和WeakReference有資格領取:

  • 第一Random沒有存儲在本地,更何況稍後讀本地。
  • 第二Random傳遞給一個WeakReference,所以會確定收集反正,但WeakReference本身沒有任何地方舉行,這樣是符合回收。

琴絃都不是(只有2個位置的字符串的情況下,沒有4,就算是達到了每一種可能的代碼路徑):因爲他們是在C#代碼文本,一旦它們的存在,他們被拘留。

+0

是的,很顯然,問題是關於'隨機'的對象,抱歉,我忘了提及這一點。 –

+0

現在,有人可以說我的答案是不正確的,並且**都是正確答案嗎?** –

+0

是的;澄清 - 請參閱更新 –

9

確實,這是實現(和編譯器)的依賴。如果這一切都採用相同的方法,則無法知道哪些對象仍在堆棧中。由於堆棧中的對象仍然被引用,因此它們將不可收集。

面試官希望你最有可能做的事情是在GC.Collect的調用下檢查哪些對象仍然可以訪問,假設一個「完美」實現,儘快丟棄所有內容。

+0

爲什麼downvote?編碼涉及GC行爲的單元測試時,知道這一點非常重要,我在這裏講述了經驗。我明確地區分了面試者可能想聽到的內容和技術現實是什麼。 – Zarat

+0

+1是我讀過的第一個正確答案。 「假設一個完美的實現」。鑑於這個問題是無稽之談,我會避免猜測面試官認爲他們在問什麼。 –

1

GC.Collect的是象Java相當於System.gc()的

它「建議」,以檢查空值刪除它們。你不能真正依賴這個特性,因爲它不像C++那樣是自動的。

希望它有幫助!

3

但是,我的面試官想聽聽別的。

我希望他們想聽到像一個馬克Gravell的答案在這裏發表而是基於垃圾回收虛擬機如何工作的一個過於簡單的模型,沒有任何相似之處現實。

例如,對GC.Collect的調用可能會得到尾部調用優化,在這種情況下,沒有全局根,因此將收集所有堆分配的塊。或者,編譯器可能會爲每個臨時文件(不只是源代碼中的變量)在堆棧幀上創建一個新條目,它使所有內容都可訪問並且不收集任何內容。或者編譯器可能交換創造串ab的順序和收集Target方法之前由WeakReference提到的Random對象調用導致null引用異常,因此其他Random是從來沒有分配。

+0

你是什麼意思交換字符串,以及如何與'WeakReference'相關? –

+0

我的意思是執行'new WeakReference(new Random())。Target.Next(0,1)== 1?在執行'new Random()之前「Whatever 1」:「Whatever 2」。Next(0,1)== 1? 「無論1」:「無論2」。 –

+0

哦,我錯過了其中的一半,早期收集'WeakReference'目標+異常可能以任意順序發生,只是如果它們被重新排序,它只會影響另一個'Random'。在這種情況下,編譯器可以自由重新排序,因爲「沒有人會知道」。 –