.net GC和应用程序根

.net GC和应用程序根,.net,memory-management,garbage-collection,clr,.net,Memory Management,Garbage Collection,Clr,jit编译器和clr维护指向堆中对象或为空的应用程序根的列表。GC用这些根创建一个图,并标记堆中在此图中引用的所有对象,其余的是垃圾。 我的问题是:根如何变为空? 最明显的情况是在代码中将变量显式设置为null。 但如果不是呢?jit/clr如何知道何时将根设置为null?我的理解是,应用程序根中包含的指针没有设置为null。这有点违反直觉(IMHO),因为处理对象的最快方法似乎就是简单地去掉指向它的指针,就像FAT文件系统只是标记一个FAT条目来删除文件一样,而不实际跟踪磁盘上的字节并将其设置

jit编译器和clr维护指向堆中对象或为空的应用程序根的列表。GC用这些根创建一个图,并标记堆中在此图中引用的所有对象,其余的是垃圾。
我的问题是:根如何变为空?
最明显的情况是在代码中将变量显式设置为null。
但如果不是呢?jit/clr如何知道何时将根设置为null?

我的理解是,应用程序根中包含的指针没有设置为null。这有点违反直觉(IMHO),因为处理对象的最快方法似乎就是简单地去掉指向它的指针,就像FAT文件系统只是标记一个FAT条目来删除文件一样,而不实际跟踪磁盘上的字节并将其设置为零。我错过了一个关于这个的采访问题,所以我读了一些关于它的内容,尽管它对我们每天担心的任何事情都没有适用性

无论如何。。。12年前,杰弗里·里克特(Jeffrey Richter)在MSDN上写了一篇文章,阐述了这一点。正是从他的文章中,我学到了以下几点

当GC运行时,它假定所有应用程序根都指向无法访问的对象。它遍历根,跟随它们找到堆上的对象(或者发现它们没有指向任何有效的对象)。它以递归的方式实现这一点,构建一个新的可到达对象图。然后它遍历堆,向下移动有效对象并修复它们的指针——其效果是整合堆顶部的可用内存。在这个过程中的某个时刻,可访问对象的图形被复制回应用程序根,并替换它们。我不确定这是在压缩堆之前还是之后发生的


12月12日和1月13日出版的MSDN杂志也有一篇关于C#内存管理的文章。我没有读过它,但计划读一读——它可能会澄清所有这一切。

还有一种情况:当您离开作用域时,代码块中定义的局部变量变得不可访问,因为您失去了函数stackframe,从而失去了对该对象的引用。