2017-02-18 145 views
0
void method() 
{ 
    Type obj = new Type() ; 
} 

也許我誤解了某些東西,但是當函數返回並且堆棧解開後,'obj'必須以某種方式從根集合中刪除。這個機制如何工作?我已經搜索了here並將其搜索到了,但沒有發現任何內容來澄清我的問題。垃圾收集器如何保持從堆棧跟蹤根

+0

.NET GC是一個標記和清掃收集器。如果在標記階段沒有找到對象,它就會變甜:)請注意,「obj」從來就不是根集的一部分,它是從堆棧爬取階段引用的。我不能深入細節,因爲你的問題是相當廣泛的,也許試圖解釋你*不明白的東西。 –

+0

@LucasTrzesniewski,當在線程中調用函數時,必須注意在調用堆棧中創建的引用。當函數退出時,垃圾收集器不能再檢查引用,是的。如果是這樣,那麼它是如何實現的? –

回答

2

沒有「減法」,這將使調用方法完全過於昂貴。這裏的主要角色是即時編譯器。它不僅僅將MSIL轉換爲機器碼,還會生成一個表,描述方法如何使用對象。該表包含對象使用的代碼位置的地址以及它的存儲位置。

注意堆棧是如何抽象的,存儲對象引用的更常見的地方是在處理器寄存器中。 GC需要知道哪些寄存器用於正確跟蹤對象使用情況。如果確實溢出堆棧,則堆棧幀偏移。

當垃圾回收器開始時,它遍歷堆棧,遍歷活動方法的堆棧幀。並使用與每種方法關聯的表來查找對象引用。有一個很大的好處,就是當一個方法完成時沒有什麼特別的事情需要完成,堆棧框架根本就不存在了。該表還使垃圾收集非常高效,即使該方法還沒有完成執行,也可以收集對象。比如,你的Main()方法很重要,你不希望你在該方法中使用的任何對象在應用程序的整個生命週期內泄漏。它使得fixed聲明非常便宜,表格只是簡單地表示該對象不應被移動。

該表的存在是託管和非託管代碼之間的區別。更多關於this answer中的表格。

+0

是否記錄在某處? –

+0

不是我所知道的,你必須閱讀CLR源代碼。我懷疑傑弗裏·裏希特在他的書中會提到它,自從我閱讀一本書的時間太長了。 GitHub上的CoreCLR是查看類似內容的好方法。或者當然:) –

+2

@GreenTree在[BOTR](https://github.com/dotnet/coreclr/blob/master/Documentation/botr/README.md)中記錄了一小部分,更確切地說[在這裏] (https://github.com/dotnet/coreclr/blob/master/Documentation/botr/ryujit-overview.md#gc-info)。您也可能對[GC章節](https://github.com/dotnet/coreclr/blob/master/Documentation/botr/garbage-collection.md)感興趣。 –