I'm trying to find some memory leaks in our application using memory profiler 6. In the application I dynamically add and remove RadPane tabs (Telerik Docking). I want to make sure that after closing a tab, it is garbage collected.
Memory profiler says that all instances are still held in memory, but by a weak reference (GC Root - Yes -- Weak Reference). To me this at first meant that the GC would, at some point, come around and collect them. No matter how many snap shots I take, those objects are never collected.
I then go suspicious and took a snap shot while the tabs are still open (and should not be collected). To my suprise they also have the GC Root - Yes -- Weak Reference attribute.

Could you explain, what that attribute exactly means? Does it mean that the shortest route to a GC Root is a weak reference? This would not be very useful, as one would be most interested in the non-weak reference route to a GC root.

When .NET creates a weak reference (usually via the WeakReference class), the internal implementation is done by making the object a garbage collection root marked as weak, which means that the object will be collected if there are no other references to it. This is done so that the object managing the weak reference knows when it is collected.

The memory profiler will reveal these kinds of root in the object list. A single object can be a GC root for many different reasons, the 'weak reference' reason is only displayed if it's the only reason that an object is a root. These types of root are otherwise ignored, so the 'distance to root' value is the distance to the nearest strong root, and the object reference graph will only show paths to strong roots.

If these objects are persisting, it's most likely because they have a strong root of some kind: the object reference graph will reveal this (you may have to switch on the display of finalizer roots if no such roots are revealed).

1) Why would you ever see GC Root -- Yes Weak Reference... ? As you say, this should only be displayed if an object is only referenced via weak references. Now, if Ants Memory profiler does a force garbage collect before taking the snapshot, shouldn't these all be removed (since there are only weak references to it)?

2) You say if they are persisting, it's because they have a strong root of some kind. Now, according to what you said before, if this was the case, it shouldn't be listed as Yes - Weak Reference, as there is a strong reference to it.

The message displays if the only reason the object is a GC root is that it's referenced by weak references, not if the only things that are referencing it are weak references. There would be no way to discover that an object has weak references pointing at

Weak references are confusingly named in a way: they aren't actually references at all. They work by creating a GC root for the object you specify. Unlike normal GC roots these don't force the object to stay in memory but just act as a placeholder. These aren't 'references' in the same way that assigning a variable creates a reference: it's two separate objects. One is usually (but not always!) a WeakReference object that knows about the GC root, and the other is the target object. 'Dereferencing' the weak reference involves looking up the object pointed to by the gc root.

Note that even with strong roots, there's no reason that an object which is a strong root can't have other references. If this were the case, you couldn't create a reference to an object stored in a static variable.

Also note that the WeakReference class isn't the only way to create a weak reference GC root: you can create them from unmanaged code, or using the GCHandle class.

The memory profiler won't show weak references in the object retention graph (as they aren't 'references' in the conventional sense), and won't count them in the distance to GC root column, so you can still use these to discover why the object is still in memory.