2013-03-19 3 views
0
// So I call this function after deleting a node. 
// It works before I delete the node, but for some reason 
// after I perform a deletion and update the tree it runs into 
// EXC_BAD_ACCESS on the line below... 

void BinaryTree::updateCost(BinaryNode *root) { 
    if (root != NULL) 
     root->updateCostRecursively(1); 
} 

void BinaryNode::updateCostRecursively(int newCost) { 
    cout << this << endl; // prints 0x3000000000000000 before the bad access 
    cost = newCost; // has a bad access here 
    if (right != NULL) 
     right->updateCostRecursively(newCost + 1); 
    if (left != NULL) 
     left->updateCostRecursively(newCost + 1); 
} 

매번 포인터를 확인할 때도 NULL 개체에서이 재귀 함수가 호출되는 이유는 무엇입니까?NULL 검사 후 포인터에서 재귀 함수가 호출되는 이유는 무엇입니까?

아래 노드를 삭제하는 데 사용하는 코드를 복사했습니다. 나는 여전히 재귀 함수를 이해하는 데 어려움을 겪고있다. 그러나 어떤 시점에서도 알 수없는 것에서 나는 매달려있는 포인터를 떠난다.

BinaryNode *BinaryTree::findMin(BinaryNode *t) { 
    if (t == NULL) return NULL; 
    while (t->left != NULL) t = t->left; 
    return t; 
} 

BinaryNode *BinaryTree::removeMin(BinaryNode *t) { 
    if (t == NULL) return NULL; 
    if (t->left != NULL) 
     t->left = removeMin(t->left); 
    else { 
     BinaryNode *node = t; 
     t = t->right; 
     delete node; 
    } 
    return t; 
} 

bool BinaryTree::remove(int key) { 
    if (root != NULL && remove(key, root)) 
     return true; 
    return false; 
} 

BinaryNode *BinaryTree::remove(int x, BinaryNode *t) { 
    if (t == NULL) return NULL; 

    if (x < t->key) 
     t->left = remove(x, t->left); 
    else if (x > t->key) 
     t->right = remove(x, t->right); 
    else if (t->left != NULL && t->right != NULL) { 
     // item x is found; t has two children 
     t->key = findMin(t->right)->key; 
     t->right = removeMin(t->right); 
    } else { //t has only one child 
     BinaryNode *node = t;  
     t = (t->left != NULL) ? t->left : t->right; 
     delete node; 
    } 

    updateCost(root); 
    return t; 
} 
+6

NULL이 아니기 때문에? 'delete'는 포인터를 수정하지 않는다. 그게 문제가 아니라면 [최소한의 테스트 케이스] (http://sscce.org)를 만드십시오. –

+2

0x3000000000000000! = 0 – fbafelipe

답변

1

오류는 게시 된 코드가 아니라 삭제 방법에 있습니다. 노드 (예 : root->right)를 삭제 한 후에 root->right = NULL을 설정해야합니다. delete을 사용하면 포인터가 가리키는 메모리를 확보 할 수 있습니다. 포인터 자체는 계속 그 주소를 가리 킵니다. 해제 된 메모리에 액세스하려고하므로 잘못된 액세스 예외가 발생합니다.

+0

노드 삭제에 사용하는 기능을 붙여 넣었습니다. 내가 말할 수있는 것에서는 매달려있는 포인터를 놓아 두지 않았지만 아마도 틀렸을 것입니다. – Yep

+0

@Yep : 디버거를 사용하여'remove' 함수를 아주 조심스럽게 실행하여이 방법을 확인하십시오. –

+0

@Yep 죄송합니다. 지금 당장 해당 코드를 자세히 살펴볼 시간이 없습니다. 한눈에 잎을 지우면 매달린 포인터가 생기는 것처럼 보입니다. – evanmcdonnal

관련 문제