简体   繁体   中英

Memory leaks in C# when using deep copy

Im making an evolutionary algorithm and I have some problems with memory leaks. Basically I have a population consisting of trees. When I perform my crossover operation between two trees I want to swap two sub-trees between the two trees. The problem is that this preocess leaks a lot of memory which results in my program being useless for over 30-40 generations. The most important code is as follows:

The class for nodes:

[System.Serializable]
public class TreeNode
{
    ArrayList mChildren = new ArrayList();
    TreeNode mParent;

public static TreeNode DeepClone<TreeNode>(TreeNode obj)
{
    using (var ms = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, obj);
        ms.Position = 0;

        return (TreeNode) formatter.Deserialize(ms);
    }
}

public TreeNode (TreeNode parent)
{
    mParent = parent;
}
}

The class for the trees:

[System.Serializable]
public class Tree
{
    TreeNode mRoot = new TreeNode(null);

    public static Tree DeepClone<Tree>(Tree obj)
    {
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;

            return (Tree) formatter.Deserialize(ms);
        }
    }
}

I've been looking at How do you do a deep copy of an object in .NET (C# specifically)? for the deep copying, but Im not sure if its implemented correctly.

As for my test program:

for (int i = 0; i < 50; i++)
{
    trees[i] = new Tree();
    trees[i].generateTree(30);
}

for (int i = 0; i < 100; i++)
{
    for (int j = 0; j < 49; j++)
    {
        trees[j].getRandomSubtree(Tree.DeepClone<Tree>(trees[j+1]));
    }
    System.GC.Collect();
}

The getRandomSubtree() function basically selects a random sub-tree from one tree and swaps it with a randomly selected sub-tree from another tree. I also make sure to update the parent reference of the sub-trees. When I run this code my program is leaking a lot of memory. If I stop making deep copys the program stops leaking memory so something is going on that I quite dont understand.

I don't think you want to serialize the parent field. Mark it as NonSerialized . Of course, you then need to fix this after deserialization.

Or simply set it to null before serializing:

public static TreeNode DeepClone<TreeNode>(TreeNode obj)
{
    TreeNode oldParent = obj.mParent;
    obj.mParent = null;
    using (var ms = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, obj);
        obj.mParent = oldParent;

        ms.Position = 0;

        TreeNode result = (TreeNode) formatter.Deserialize(ms);
        result.mParent = oldParent;
        return result;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM