.net CLR相关问题

时间:2009-11-01 08:59:56

标签: c# .net clr

这是一个与.net CLR相关的问题。

我有3个对象对象A,B,C

反射B和B指c

如果我明确地杀死了对象“A”,那么堆中的这些对象会发生什么。哪些会被垃圾收集?(对象A或B或c或者全部?)

有些人可以详细解释这种情况下的垃圾收集过程。

提前致谢 SNA

3 个答案:

答案 0 :(得分:9)

首先 - 你不能“杀死对象”A“明确地”;您可以清除对它的引用,但这只是将局部变量设置为null,并且与托管堆上的实际对象无关。您可以Dispose(),但没有 。

一切都取决于;可以其他任何内容查看B / C?如果没有,他们符合条件进行收集。但GC不确定;它只会在它选择时发生。在某些 indeterminate 时间,GC将启动,检测到这些对象无法访问,并将其删除。在此过程中,它将检查是否有任何终结器(仍然未完成),并执行终结器(分为两步)。

人们在可达性方面经常忘记的一件事是事件;如果B / C订阅了长期存在的对象上的事件,则可以访问B / C(事件发布者)。


澄清; GC通过从根对象(线程等)构建树来工作。它走每个引用,标记可以到达的所有对象。任何未在最后标记的内容都有资格收集。这避免了由于断开的数据孤岛而导致内存泄漏的COM / COM +问题,其中X => Y和Y => X(所以X和Y都有正的ref-count,因此都不会被清除)。

答案 1 :(得分:1)

第一个误解可能是您无法明确杀死托管对象。

您可以释放自己分配的非托管内存,但不管理,也不受垃圾回收的影响。

当你将A的引用设置为null或者它超出范围时,就不会有任何对B&的引用。 C,下一个GC集合将负责处理。

答案 2 :(得分:1)

在.NET中,无法实际杀死/删除对象。您可以明确地做的就是解除对象。这不仅仅是对对象的Dispose()的简单调用。这将允许您在以后可能被垃圾收集器收集之前清理您的对象(您不能真正地使用它)。有关详细信息,请参阅IDisposable。在GC收集对象之前有机会清理对象的第二个选项是实现finalizer。与Dispose()不同,GC会自动调用它。同样,两者都是在对象可能停止存在之前清除任何资源的方法。

所以要回答你的问题,如果你的对象A被“杀死”,只有当它没有被任何其他对象引用时才会发生B和C将被“杀死”,因为它们只能通过A引用。通常你不会对这实际发生的时间有任何影响。您所能做的就是实现终结器,以便在发生时得到通知。 GC是一个后台服务,它在一个单独的线程上运行,该线程遵循复杂的逻辑,何时实际删除对象。

如果您想了解GC的工作原理,我建议您使用以下two articles。虽然有点旧,但他们仍然完全适用。