2014-01-21 56 views
-1
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循環時出現錯誤。我沒有檢測到我認爲我刪除的當前內容爲空或者不存在,所以它再次進入該指針並嘗試調用它上的刪除,然後給我提供「double free或corruption(fasttop)」錯誤。我在使用C++中的刪除操作符時遇到了問題。我在運行時總是收到「double free or corruption(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(); 
} 

我沒有絲毫線索,如何處理這個。

+0

這可能是最有效的方式來刪除BST。你爲什麼不寫一個resursive函數? –

+0

做一個後序遍歷,並通過引用刪除節點的出路? – WhozCraig

+0

'clear()'做什麼?它應該釋放整棵樹嗎?如果是這樣,你正在使這種**方式**比必要的更復雜。 –

回答

1

current = nullptr;這行不做任何事。它改變了一個立即超出範圍的局部變量。

在下一次迭代中,您將再次找到相同的節點,但是您已釋放(delete)它,因此訪問它是未定義的行爲。

您想要將指向此節點的指針更新爲BST至nullptr

+0

我認爲電流已經是指向該節點的指針了? – user3217373

+0

這是.......... –

+0

看,這裏沒有指針:'a = 3;一個= 0;'。第二次分配後'3'的值是否會改變?很明顯不是。 –

1

如果你只是想釋放樹,然後簡單地做

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

BST()析構函數應該只是刪除leftright。遞歸將其餘的照顧。

+1

對不起,我應該更加清楚。刪除樹時,我們不應該有任何內存泄漏。使用這個,valgrind顯示了一些泄漏。 – user3217373

+0

@ user3217373您正在使用valgrind ?. *優秀*。只是想提到這一點。 – WhozCraig

+0

「遞歸會照顧剩下的......」,除非樹足夠深以至於遞歸溢出堆棧。 –

0

變量「current」在while (1) {}塊內部定義,並在每次迭代時通過具有「root」值的循環進行初始化,所以在第一次通過循環時,刪除左/右分支,然後你刪除「root」,設置當前== nullptr。但是,您然後重複該循環並再次將當前電流重新定義爲「root」的值。這會導致你嘗試刪除分支和「根」,再次免費。

將「current」的定義移到while(1)循環的外部。或者更好的是,刪除while(1)循環,因爲它不需要,你總是退出一次迭代。

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

我想這部分執行刪除過程反覆

相關問題