2017-02-18 146 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)感兴趣。 –