views:

85

answers:

3

How smart is Garbage Collection when it comes to nested references?

Take this code for example:

Public Class SomeClass
    Private m_SomeOtherClass(Me)
End Class

I know that GC works by looking at how many references remain, and any object without any references ends up getting dumped. So in this case, where there's a reference coming from a member variable, is that a memory leak waiting to happen (unless you implement IDisposable, etc)?

Right now I'm assuming that the GC is smart enough for this, since it could probably check to see if any references are coming from the object itself, and just not count them towards the reference count. But I thought I would dig a little.

+4  A: 

It's absolutely fine. The GC works from a set of roots (local and static variables, etc) and finds all the references it can. If nothing else references this mutually-referencing object, it will be eligible for collection.

Jon Skeet
In other words, the child object shares the same root as the parent, and so it only counts as a self-reference.
Joel Coehoorn
Well, it might. The child object *might* be directly referenced from elsewhere, of course, in which case it would keep the "parent" object alive. Basically the right thing happens :)
Jon Skeet
Great, thanks for the answer Jon!
Brian MacKay
+1  A: 

The GC is smart enough. It will even collect both objects at the same time, if they're allocated close enough to each other in the time and space dimensions ;)

__grover
+1  A: 

Basic answer: It's not a problem.

I've heard this kind of question before and it stems from a confusion with Reference Counting, where circular referencing does pose a problem.

The .NET collector doesn't count references, it just scans and flags referenced objects. Those flags also prevent it from going into a loop. This is a very simple and virtually foolproof mechanism. The system doesn't need to count or track inbound references, so there is zero overhead for shortlived references. But you have to keep an eye on where references exist, a common problem are objects that subscribe to events. The event keeps a reference, so you need to unsubscribe before the subscribing object can be reclaimed. Another benefit of GC is that the logic also works in reverse: whenever your code has access to a reference that reference is guaranteed to be valid, simply because that reference exists.

Reference counting requires the compiler to inject code every time a reference is changed, copied or goes out of scope, incurring a constant overhead. When the count drops to zero the object can be immediately destroyed. The system needs a mechanism to (manually) handle cycles. You can find some horror stories by searching for the COM IUnknown interface.

Henk Holterman
So it starts from a set of roots, and walks out, and anything that isn't referenced goes. And it isn't actually counting references at all, I take it?
Brian MacKay
Right, I'll expand the answer a bit.
Henk Holterman