![](/img/trans.png)
[英]Seg-fault on some runs and not on others (with the same input file)
[英]Seg-Fault at BST remove() Function
基本上,該程序由BST類組成,該類指向二叉樹的第一個節點,並且這些節點也是它們自己的類。
BST調用此成員函數:
void remove(const T& x)
{
removeNode(m_root, x);
return;
}
這是remove節點的遞歸部分,運行到完成:
template <typename T>
void removeNode(TreeNode<T>* &p, const T& x)
{
if(p == NULL)
return;
if(x < p -> m_data)
removeNode(p -> m_left, x);
else if(x > p -> m_data)
removeNode(p -> m_right, x);
else
{
TreeNode<T>* tmp = new TreeNode<T>;
if(p -> m_left == NULL)
{
tmp = p -> m_right;
delete p;
p = tmp;
}
else if(p -> m_right == NULL)
{
tmp = p -> m_left;
delete p;
p = tmp;
}
else
{
tmp = p -> m_right;
TreeNode<T>* tmp2 = new TreeNode<T>;
while(tmp -> m_left != NULL)
{
tmp2 = tmp;
tmp = tmp -> m_left;
}
p -> m_data = tmp -> m_data;
if(tmp2 != NULL)
removeNode(tmp2 -> m_left, tmp -> m_left -> m_data);
else
removeNode(p -> m_right, p -> m_right -> m_data);
}
}
return;
}
我在remove()函數返回時出現段錯誤,我想知道為什么?
用戶@WhozCraig指出了代碼中最重要的錯誤:您分配了永不使用(永不銷毀!)的對象:
TreeNode<T>* tmp = new TreeNode<T>;
TreeNode<T>* tmp2 = new TreeNode<T>;
后一個分配導致條件
if(tmp2 != NULL)
永遠滿意,這會阻止您執行
else
removeNode(p -> m_right, ...)
科。
編輯
假設您有一個包含2個,5個和7個鍵的三節點樹。讓我們分別表示節點node2
, node5
和node7
。 假設node5
是樹根。 假設您還要卸下鑰匙5。
然后:
*p == node5
; if
不滿足s,則前三個,控制權傳遞給else
分支; tmp
分配給p->m_right
,即&node7
; tmp2
被分配了一個新的“空”對象-我們稱它為nodeEmpty
; node7
沒有子tmp->m_left
,因此tmp->m_left
為NULL
,並且while
循環被跳過,沒有迭代; p->m_data = tmp->m_data
使node5
獲得密鑰7; tmp2 == &nodeEmpty
不為NULL
,您調用
removeNode(tmp2 -> m_left, tmp -> m_left -> m_data)
這顯然將要從nodeEmpty
( nodeEmpty
)的不存在的左子樹中刪除某些內容, 但是...
但是,此時tmp == &node7
,而node7
沒有子級,因此tmp->m_left == NULL
。 因此,訪問tmp->m_left->m_data
會觸發內存訪問錯誤,並且在遞歸調用removeNode
之前,進程會崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.