我以前在这里看到过这个问题,特别是
通用二进制树节点析构函数问题和二进制搜索树析构函数
但到目前为止,我得到的答案是在构造函数中将Node指针设置为NULL。这是我的Node和Tree的构造函数和析构函数的代码。
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);
以上作品,到目前为止还不错。
插入方法/函数用于创建NEW节点。然后我尝试使用以下每一个(一个接一个),它们都会导致segfault(核心转储):
delete bt->getRoot();
这导致了segfault。然后我尝试了
delete bt->getRoot()->getRight();
再次出现segfault。所以上次我试过
delete bt;
静止分段
我原本以为其他节点无法访问会导致内存泄漏(我用valgrind运行它),但令我惊讶的是,valgrind崩溃了,gcc和clang甚至没有打印出任何警告,即使使用-Wall。我需要关于如何正确地做这件事的建议。提前谢谢。
这会把搞砸的
~BinaryTreeNode<Type>() {
delete left;
delete right;
delete parent;
}
删除左边,然后删除右边。看起来不错。但由于下一行而失败
现在删除父对象。然后调用父级析构函数来删除左、右和父级。因此,通过删除你的父母,你会对自己调用delete,但你已经处于删除过程中,因为其他人试图调用delete。这并不是你进入一个永远不会退出的递归循环的唯一问题。
尝试:
~BinaryTreeNode<Type>() {
delete left;
delete right;
}
父母应该删除他们的孩子,因为他们拥有自己的孩子
但孩子不应该删除那里的父母(因为孩子不拥有父母)。
如果您使用C++技术而不是C技术,这将是显而易见的(并且是自动完成的)。查找std::unique_ptr<>
。
PS。您的对象也存在根本缺陷,因为您没有实现三(C++11中的五)规则。
如果您的调用顺序是
delete bt->getRoot();
delete bt->getRoot()->getRight();
delete bt;
然后,当您删除一个节点,然后使用同一节点本身调用一个方法时,它将产生一个问题。订单应为
delete bt->getRoot()->getRight();
delete bt->getRoot();
delete bt;
移除delete bt->getRoot()->getRight();
(用于更多内存泄漏:)或将其移动到delete bt->getRoot();
之前的行