For instance if I have a hierarchical data structure:
class Node
{
public List<Node> children;
}
and it is populated to many levels down then in one of the parents go:
myNode.children.Clear();
which will clear all the references to the immediate children - but how about all the grand children, grand grand children etc. that were referenced by those immediate children? Is C# clever enough to know they are no longer needed and they will be garbage collected?
I have read using WPF data binding without implementing interface INotifyChanged can cause memory leaks: http://blogs.msdn.com/b/micmcd/archive/2008/03/07/avoiding-a-wpf-memory-leak-with-databinding-black-magic.aspx, how is that possible in a managed environment?
A memory leak is basically a piece of memory that is no longer required for the proper behavior of a program but cannot be freed due to a programming mistake. So the concept of memory leaks has nothing to do with Garbage Collection, C#, or Java.
Take this example:
Note how elements in the list are memory leaks because they are referenced by variables
a1 ... an
This is just a simple example of why it is not just up to C# to take care of memory leaks. It is also the responsibility of the developer to fix this:
This will tell the C# garbage collector that all these elements should be collected.
The garbage collector only collects objects that are no longer used - memory leaks are caused by objects still holding references to objects even though they shouldn't.
In your case, if a grand children is used by another object, then .Clear will remove it from the List of Nodes, but the garbage collector will not collect it. It will collect all other grand children though.
Example:
Yes, the garbage collector will work out that the grandchildren etc are garbage. Basically, if there's no way of getting to an object, it's considered garbage and eligible for collection.
As for how memory "leaks" are possible in managed code - it's typically if you end up with an object which is reachable via object references, but where there's no way you can end up "clearing" those references via an API.
That's the case in the blog post you quoted:
So there's this global table maintaining references, and you have no way of indicating that an item in the table can be cleared.
As an aside, you can also get memory leaks in .net if you use the unsafe keyword. If you use pointers in the same fashion as c++ etc and aren't careful to ensure you don't "loose" a pointer reference then the GC wouldn't be able to collect it.
example of unsafe block;
Sure, with C# especially short of the other reference allocation things everyone has talked about, if you have a class that wraps native resources but it's never disposed of (or you lose the reference to it), you can create a leak.
Here is an example from the Image class:
Image
is disposable, so since I'm disposing of the image at the end there shouldn't be a leak right? Actually, the fact that you overwrite the reference each time with a new image, means you can't dispose of the underlying GDI+ resources that the old image reference held. This will introduce a memory leak.Since the gc doesn't call dispose for you and the
Image
class doesn't override theFinalize
method (and call Dispose there), then you've got yourself a leak.Yes, you can have a whole graph of objects (massive data structure) but if none of it is tied down or referred to, it will be garbage collected.
If it's not, either the GC hasn't run (you could try a
GC.Collect()
for diagnostic purposes but you shouldn't use it in production code) or something is referring to a part of the structure. For example, the UI might be bound to it.