尝试删除二叉树中的节点时双重释放或损坏(out)

时间:2016-11-17 15:24:38

标签: c++ memory-management

我正在尝试创建一个递归函数来删除二叉树中的所有节点,其中p-> left和p-> right是指向树中下一级别的指针。但是它会给出以下错误消息:

*`./test.out'出错:双重免费或损坏(外出):0x00007ffdf0cb3650 *

struct Node {
    int key;
    double data;
    Node * right;
    Node * left;
};

void delete_tree(Node * & p){
  if (p->left){
    delete_tree(p->left);
  }
  if (p->right){
    delete_tree(p->right);
  }
  delete p;
};

int main(){
  Node * currentNod = new Node;
  currentNod->key = 5;
  Node * newNode = new Node;
  newNode->key = 3;
  Node * newNode2 = new Node;
  newNode2->key = 6;
  delete_tree(currentNod);
  std::cout << currentNod->key << "\n";
  std::cout << newNode->key << "\n";
  std::cout << currentNod->left->key << "\n";
  return 0;

我在网上搜索并意识到当你有指针的递归函数时会出现问题,但是delete_tree需要引用而不是副本,所以这个问题不适用于此?我不明白为什么它不起作用:(

编辑:更改了代码,问题是当我初始化currentNod时我首先创建了一个Node对象,然后我让currentNod成为该对象的指针。当我像这样初始化它时,它的工作原理。但是,它没有打印出我期望的内容。这打印:

0 3 分段错误

当我希望它立即给出分段错误时。有谁知道现在可能出现什么问题?谢谢:)

2 个答案:

答案 0 :(得分:1)

将它重新构建为析构函数会更有意义:

class Node {
public:
    // some constructor, methods, ...
    // destructor
    ~Node();
private:
    int key;
    double data;
    Node * right;
    Node * left;
};

Node::~Node(){
    delete left;
    delete right;
    left = right = nullptr; // see note below
};

然后,您只需要delete node;删除树的所有内容。但如果它是一个子树,你还需要确保父节点指向该节点的指针也是无效的,这样你就不会双重删除。

答案 1 :(得分:0)

好的,我认为你的问题是由于struct Node的初始化不正确。由于您以递归方式擦除所有树,因此必须确保仅删除已分配的动态内存,即必须确保仅删除已保留动态内存的节点,否则将进行编译但会在运行时生成错误。也就是说,在加入树结构之前正确初始化节点应该如下:

struct Node myNode:
myNode.right=NULL;
myNode.left=NULL;

通过上面我们确保树的终端节点指向NULL地址,因此当我们递归删除时,我们将只删除不指向该地址的节点。然后函数的新代码void delete_tree(Node *&amp; p)然后函数的代码工作:

void delete_tree(Node * & p){
 if (p->left){
  delete_tree(p->left);//Only deleted if p->left is different from NULL
 }
 if (p->right){
  delete_tree(p->right);//Only deleted if p->right is different from NULL
 }
 delete p;
 p=NULL; //Good Programming Practice
};