【问题标题】:Segmentation fault when accessing BST child nodes. Why?访问 BST 子节点时出现分段错误。为什么?
【发布时间】:2015-03-31 01:11:56
【问题描述】:

当我尝试访问以下定义中的 (x->left) 时,函数 tdeleteLeft(x) 中发生分段错误:

void BST::tdeleteLeft(Node* x){
    if (x->left == NULL){
        tdelete(x);
        }
        else{
        Node* y;
        y = max(x->left);
        tdelete(x->left);
        x = y;}
}

这是完整的程序:

#include <iostream>
#include <ctime>  
#include <cstdlib>
#include <iostream>

using namespace std;


class BST {
    public:
    typedef struct node {
              int value;         
              struct node *left;  
              struct node *right; 

              node() {
                left = NULL;
                right = NULL;
                }
       }Node;

    Node *root;
    Node* i;
    Node* y;
    int z;
    static int c;


    int count();
    void inc();
    BST(int n);
    void tdelete(Node* x);
    Node* max(Node* x);
    void remove_node(Node* x);
    Node* min(Node* x);
    void tdeleteLeft(Node* x);
    void insert(Node* tree, int val);

};




int main ()
{  
  // create BST tree with n nodes
  BST *tree = new BST(10);

  clock_t t;
  t = clock();
  tree->remove_node(tree->root);
  t = clock() - t;
  cout << t << " clicks " <<  ((float)t)/CLOCKS_PER_SEC << "seconds).\n" << endl;

  return 0;
}




BST::BST(int n){
    c = 1;
    z = 0;
    Node *root = NULL;
    for (int i=0; i<n; i++){
        int rando = rand() % 10;
        insert(root, rando);
        }
    cout << "created " << n << "-node BST" << endl; 
}

int BST::c;

int BST::count(){
    return c;
    }

void BST::inc(){
    c++;
    }


BST::Node* BST::max(Node* x){
    if (x->right == NULL){
        return x;
        }
    else
        return max(x->right);   
    }

BST::Node* BST::min(Node* x){
    Node* i = x;
    while (i->left !=NULL){
        i = i->left;
        }
    return i    ;
    }


void BST::tdelete(Node* x){
    if (x->right!=NULL){
        tdelete(x->right);
        }
    if  (x->left!=NULL){
        tdelete(x->left);
        }
    delete(x);
    }

void BST::tdeleteLeft(Node* x){
    if (x->left == NULL){
        tdelete(x);
        }
        else{
        Node* y;
        y = max(x->left);
        tdelete(x->left);
        x = y;}
}

void BST::remove_node(Node* x){
    tdeleteLeft(x);
}



void BST::insert(Node *tree, int val){

               if(tree==NULL){
                    BST::Node* tree = new BST::Node();
                    tree->left = NULL;
                    tree->right = NULL;
                    tree->value = val;
                    c++;
                    }
               else{
                    if(c%2==0){
                        insert(tree->left, val);}
                    else
                    insert(tree->right, val);}

}

【问题讨论】:

  • 显然函数 tdeleteLeft 是用 x = NULL 调用的,为此添加一个 if 语句,在 if 语句中添加一个断点并检查调用堆栈以了解为什么会发生这种情况。
  • 那我认为当我调用我的 BST 构造函数时,我的插入函数一定有问题。

标签: c++ segmentation-fault binary-search-tree


【解决方案1】:

一方面,在BST::BST(int)中声明局部变量root

BST::BST(int n){
    c = 1;
    z = 0;
    Node *root = NULL;  // <--- This defines a local variable which shadows BST::root
    for (int i=0; i<n; i++){
    ...

shadows 同名成员。相应地,main 中的tree-&gt;root 在调用构造函数后保持未初始化状态。 结果tree-&gt;remove_node(tree-&gt;root) 尝试删除未初始化指针的“左”节点,这会导致您观察到的分段错误。要解决这个问题,您需要删除 root 变量的本地声明:

BST::BST(int n){
    c = 1;
    z = 0;
    for (int i=0; i<n; i++){
    ...

那么你应该注意insert(root, rando)不会更新调用者上下文中的root变量,因为指针是按值传递的,所以分配的树节点变得不可访问。为了防止这种情况,您可以返回更新后的根节点:

Node* BST::insert(Node* tree, int val){

    if(tree==NULL){
        tree = new BST::Node(); // careful about shadowing the "tree" argument
        ...
    }
    else{
        if(c%2==0){
            tree->left  = insert(tree->left, val);
        }
        else{
            tree->right = insert(tree->right, val);
        }
    }
    return tree;
}

你会像这样在构造函数中调用它:

BST::BST(int n){
    c = 1;
    z = 0;
    for (int i=0; i<n; i++){
        int rando = rand() % 10;
        root = insert(root, rando);
    }
}

或通过引用传递指针:

void BST::insert(Node*& tree, int val){
   ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-06
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 2021-06-21
    • 1970-01-01
    相关资源
    最近更新 更多