Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have a memory leak in managed code? (specifically C# 3.0)

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?

like image 452
markmnl Avatar asked Jun 22 '11 07:06

markmnl


2 Answers

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:

There is an issue where WPF checks to find things that implement INotifyProperyChanged. If there is a databinding to something not implementing this interface, then it makes a record in a global table. That record doesn't get cleaned up, as WPF has no way of checking when that DB record is no longer needed.

So there's this global table maintaining references, and you have no way of indicating that an item in the table can be cleared.

like image 134
Jon Skeet Avatar answered Nov 15 '22 16:11

Jon Skeet


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:

class Foo {
 public Node SomeProperty {get; set;}

    public void SomeFunction(){
        var node = new Node { children = new List<Node>() };
        var childNode = new Node();
        var childNode2 = new Node();
        node.children.Add(childNode);
        node.children.Add(childNode2);
        SomeProperty = childNode2;

        node.children.Clear();
        // childNode will be garbage collected
        // childNode2 is still used by SomeProperty,
        // so it won't be garbage collected until SomeProperty or the instance
        // of Foo is no longer used.
    }
}
like image 44
Michael Stum Avatar answered Nov 15 '22 14:11

Michael Stum