2009-11-01 59 views
1

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

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

甲refres B和B是指Ç

如果我杀对象碰巧这些对象在堆中什么 “A” explicitly.Which将是垃圾收集?(对象A或B或C或全部?)

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

在此先感谢 SNA

+0

你怎么杀A? – 2009-11-01 09:04:22

回答

9

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

这一切都取决于;可以别的看到B/C?如果不是,他们是合格收集。但GC是非确定性的;它只在选择时才会发生。在某些未确定的时间内,GC将启动,检测到这些对象无法访问,并将其删除。在这个过程中,它将检查是否有终结者(仍然未完成),并执行终结者(分两步处理)。

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


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

1

第一个误解可能是你不能明确地杀死一个托管对象。

您可以释放自己分配的非托管内存,但这不是托管内容,也不受垃圾回收的限制。

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

1

在.NET中,没有办法实际杀死/删除一个对象。你可以明确地做的是抛弃一个对象。这只不过是对对象的简单调用Dispose()。这将允许你清理你的对象,然后再由垃圾收集器收集它(你不能真正的富裕)。有关更多详细信息,请参阅IDisposable。第二个选项是在GC收集之前有机会清理您的对象,以实现finalizer。与Dispose()不同,它将自动被GC调用。同样,这两种方法都是在对象可能停止存在之前清除所有资源的方法。

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

如果你想了解GC的工作原理,我会建议以下twoarticles。虽然有点老,但他们仍然完全适用。