1

我在这里看到过这个问题,特别是

通用二叉树节点析构函数问题 和 二叉搜索树析构函数 等

但到目前为止,我得到的答案是在构造函数中将节点指针设置为 NULL。这是我的节点和树的构造函数和析构函数的代码。

template <class Type>
class Node {
protected:
    Type data;
public:
    Node<Type>(Type data) { this->data = data; }
};

二叉树节点继承自上面的节点(我知道不使用继承会更容易,直接使用 BinaryTreeNode 直接处理数据,但我选择这样做是因为我正在练习)

BinaryTreeNode 类:

template <class Type>
class BinaryTreeNode: public Node<Type> {
protected:
BinaryTreeNode<Type> *left;
BinaryTreeNode<Type> *right;
BinaryTreeNode<Type> *parent;
public:
BinaryTreeNode<Type>(Type data) : Node<Type>(data) {
    this->left = NULL;
    this->right = NULL;
    this->parent = NULL;
}
~BinaryTreeNode<Type>() {
    delete left;
    delete right;
    delete parent;
}
};

对于树:

template <class Type, template <class> class NodeType = BinaryTreeNode>
class BinaryTree {
protected:
    int size;
    NodeType<Type> *root;
public:
    ~BinaryTree<Type, NodeType>() {
        delete root;
    }
    BinaryTree<Type, NodeType>() {
        this->size = 0;
        this->root = NULL;
    }
};

现在主要是,我执行以下操作:

BinaryTree<int> *bt = new BinaryTree<int>();
bt->insert(100);
bt->insert(50);
bt->insert(101);

以上工作,到目前为止一切顺利。

插入方法/函数是创建新节点的地方。然后我尝试使用以下每一项(一个接一个),它们都会导致段错误(核心转储):

delete bt->getRoot();

这导致了段错误。然后我尝试了

delete bt->getRoot()->getRight();

又是段错误。所以最后我尝试了

delete bt;

仍然是段错误

由于其他节点无法访问(我正在使用 valgrind 运行它),我原以为只是内存泄漏,但令我惊讶的是,valgrind 崩溃了,即使使用 -Wall,gcc 和 clang 甚至都没有打印出任何警告。我需要有关如何正确执行此操作的建议。提前致谢。

4

3 回答 3

3

这会让你搞砸的

~BinaryTreeNode<Type>() {
    delete left;
    delete right;
    delete parent;
}

删除左边,然后删除右边。看起来不错。但由于下一行而失败。
现在您删除父级。然后调用父母析构函数来删除左右和父母。因此,通过删除您的父母,您然后对自己调用删除,但您已经处于删除中间,因为其他人试图调用删除。这不是您进入永远不会退出的递归循环的唯一问题。

尝试:

~BinaryTreeNode<Type>() {
    delete left;
    delete right;
}

父母应该删除他们的孩子,因为他们拥有自己的孩子。
但是孩子不应该删除那里的父母(因为孩子不拥有父母)。

如果您使用的是 C++ 技术而不是 C 技术,这将是显而易见的(并且是自动完成的)。抬头看std::unique_ptr<>

PS。您的对象也存在根本缺陷,因为您没有实现三规则(C++ 11 中的五)。

于 2013-08-05T05:02:26.737 回答
0

如果您的调用顺序是

delete bt->getRoot();
delete bt->getRoot()->getRight();
delete bt;

然后它会在您删除节点然后使用同一节点本身调用方法时产生问题。顺序应该是

delete bt->getRoot()->getRight();
delete bt->getRoot();
delete bt;
于 2013-08-05T04:45:36.433 回答
0

删除delete bt->getRoot()->getRight();(更多内存泄漏:))或将其移至之前的行delete bt->getRoot();

于 2013-08-05T04:49:32.453 回答