我在使用C ++中的delete运算符时遇到了问题。我跑步时不断出现“双重免费或腐败(快速顶部)”错误

时间:2014-01-21 02:05:37

标签: c++ memory binary-search-tree delete-operator

void clear() {
  while(1)
  {
    BSTNode<Data> *current = root;
      if(!current)
      {
        return;
      }

    while(current->left)
    {
      current = current->left;
    }

    while(current->right)
    {
      current = current->right;
    }
    delete current;
    current = nullptr;
    //std::cout << current->parent->data << std::endl;
  }
}

所以我非常有信心我用BST做了其他所有事情,就像排序,插入和不做什么一样。如果我们假设所有这一切都是正确的。我只是想删除树中的所有节点。但是第二次运行while循环时我得到并出错。我没有检测到我认为我删除的当前是null还是没有,所以它再次进入该指针并尝试调用它上面的删除然后给我“双重自由或损坏(fasttop)”错误。

*** glibc detected *** ./bst: double free or corruption (fasttop): 0x083770b0 ***
======= Backtrace: =========
/lib/libc.so.6[0x975e31]
/software/common/gcc/lib/libstdc++.so.6(_ZdlPv+0x1f)[0x266b8f]
./bst[0x804976e]
./bst[0x804919a]
./bst[0x8048ff4]
/lib/libc.so.6(__libc_start_main+0xe6)[0x91bd26]
./bst[0x8048981]
======= Memory map: ========
0021f000-002fa000 r-xp 00000000 00:14 3229873    /software/common/gcc-     4.8.1/lib/libstdc++.so.6.0.18
002fa000-002fe000 r--p 000db000 00:14 3229873    /software/common/gcc-4.8.1/lib/libstdc++.so.6.0.18
002fe000-002ff000 rw-p 000df000 00:14 3229873    /software/common/gcc-4.8.1/lib/libstdc++.so.6.0.18
002ff000-00306000 rw-p 00000000 00:00 0
0045c000-0045d000 r-xp 00000000 00:00 0          [vdso]
00752000-00770000 r-xp 00000000 fd:00 42112      /lib/ld-2.12.so
00770000-00771000 r--p 0001d000 fd:00 42112      /lib/ld-2.12.so
00771000-00772000 rw-p 0001e000 fd:00 42112      /lib/ld-2.12.so
00774000-0079c000 r-xp 00000000 fd:00 44717      /lib/libm-2.12.so
0079c000-0079d000 r--p 00027000 fd:00 44717      /lib/libm-2.12.so
0079d000-0079e000 rw-p 00028000 fd:00 44717      /lib/libm-2.12.so
00905000-00a96000 r-xp 00000000 fd:00 42155      /lib/libc-2.12.so
00a96000-00a98000 r--p 00191000 fd:00 42155      /lib/libc-2.12.so
00a98000-00a99000 rw-p 00193000 fd:00 42155      /lib/libc-2.12.so
00a99000-00a9c000 rw-p 00000000 00:00 0
00b20000-00b3b000 r-xp 00000000 00:14 3229870    /software/common/gcc-4.8.1/lib/libgcc_s.so.1
00b3b000-00b3c000 rw-p 0001a000 00:14 3229870    /software/common/gcc-4.8.1/lib/libgcc_s.so.1
08048000-0804d000 r-xp 00000000 00:1a 31125426   /home/linux/ieng6/cs100w/bhn013/P1/bst
0804d000-0804e000 rw-p 00004000 00:1a 31125426   /home/linux/ieng6/cs100w/bhn013/P1/bst
08377000-08398000 rw-p 00000000 00:00 0          [heap]
b77d1000-b77d4000 rw-p 00000000 00:00 0
b77ec000-b77ef000 rw-p 00000000 00:00 0
bfa01000-bfa17000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

这是完整的错误消息。

这就是它......我用这几行代码清楚地说:

virtual ~BST() {
clear();
}

关于如何处理这个问题我没有丝毫的线索。

4 个答案:

答案 0 :(得分:1)

current = nullptr;此行无效。它会更改一个立即超出范围的局部变量。

在下一次迭代中,您将再次找到相同的节点,但您释放了它(delete),因此访问它是未定义的行为。

您希望将BST中此节点的指针更新为nullptr

答案 1 :(得分:1)

如果您只是想释放树,那么只需执行

即可
void clear() {
    delete root;
    root = nullptr;
}

BST()的析构函数应该只删除leftright。递归会照顾其余部分。

答案 2 :(得分:0)

变量&#34; current&#34;在while (1) {}块内部定义,并在每次迭代时通过循环初始化,其值为&#34; root&#34;,因此第一次通过循环,删除左/右分支然后你删除&#34; root&#34;,设置current == nullptr。但是,然后重复循环并将当前值重新定义为&#34; root&#34;再次。这会导致您尝试删除分支和&#34; root&#34;一遍又一遍,双重自由。

移动&#34;当前&#34;的定义在while(1)循环之外。或者更好的是,删除while(1)循环,因为它不需要,你总是退出一次迭代。

答案 3 :(得分:0)

while(current->left || current->right)
{
  if(current->left)
  {
    current = current->left;
  }
  else if(current->right)
  {
    current = current->right;
  }
}
delete current;

我想这部分会迭代地执行删除过程