当使用深度复制时,c#中的内存泄漏

本文关键字:内存 泄漏 深度 复制 | 更新日期: 2023-09-27 17:54:29

我正在做一个进化算法,我有一些内存泄漏的问题。基本上我有一个由树组成的种群。当我在两棵树之间进行交叉操作时,我想在两棵树之间交换两个子树。问题是这个进程泄漏了大量内存,导致我的程序在30-40代以上都是无用的。最重要的代码如下:

节点的类:

[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;
}
}

树的类:

[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);
        }
    }
}

我一直在看如何在。net(特别是c#)中对对象进行深度复制?用于深度复制,但我不确定它是否实现正确。

对于我的测试程序:

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();
}

getRandomSubtree()函数基本上是从一棵树中随机选择一颗子树,并将其与另一棵树中随机选择的一颗子树交换。我还确保更新了子树的父引用。当我运行这段代码时,我的程序泄漏了大量内存。如果我停止深度拷贝,程序就会停止内存泄漏,所以我不太明白发生了什么。

当使用深度复制时,c#中的内存泄漏

我不认为你想要序列化父字段。标记为NonSerialized。当然,您需要在反序列化之后修复这个问题。

或者在序列化之前将其设置为null:

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;
    }
}