【问题标题】:segmentation fault after calling a toString function twice两次调用 toString 函数后出现分段错误
【发布时间】:2020-08-04 10:14:01
【问题描述】:

我目前正在编写一个左子右兄弟类。我的 addSibling 函数和我的 toString 函数没有按预期工作。我希望以升序的 ASCII 值对兄弟姐妹进行排序,并让我的 addSibling 函数在根内的字符重复时返回 false。 我的头文件有一个类 CT​​ree,它具有公共成员数据、孩子、同胞、上一个和函数声明。奇怪的是当我创建一个测试并尝试输出一个带有它的孩子的根时,

CTree* t1 = new CTree('A') ;
    assert(t1->toString() == string("A\n"));

    // A
    // |
    // b
    assert(t1->addChild('b'));


    cout<<t1->toString();
    cout<<t1->toString();

这给了我一个分段错误

我的 cpp 文件:

using std::string;

CTree::CTree(char ch)
  :data(ch),kids(nullptr),sibs(nullptr),prev(nullptr){
}

CTree::~CTree(){
  if(kids!=NULL){
    delete kids;
  }
  if(sibs!=NULL){
    delete sibs;
  }
}

bool CTree::addChild(char ch){
  //if there is a kid, add ch as the sib of the kid
    if (kids){
      if (kids->data==ch){
        return false;
      }

      bool temp=kids->addSibling(ch);
      return temp;
    }
    else{
    //if there is not a kid, create CTree ch that is the child of this
      CTree temp(ch);
      kids=&temp;
      return true;
    }
}
bool CTree::addSibling(char ch){
  //create a CTree, and call addSibling with &CTree
    CTree temp(ch);
    return this->addSibling(&temp);
}


bool CTree::addSibling(CTree *root){
  //initialize prev
    prev=this;
    //loop over sibs in a recursive fashion, and comparing the values
    while (sibs){
      //if the char in sib and root is the same return false
      if (sibs->data==root->data){
          return false;
        }
      //if the char in sib is smaller than root then continue moving forward
      else if((sibs->data)<(root->data)){
          prev=sibs;
          sibs=sibs->sibs;
      }
      //when the char in sib is bigger than the root, put root as the sib of prev
      else {
          prev->sibs=root;
          return true;
      }
//if sib points to null and there exist no sib that is bigger than the root, put root as the last sib

    if (prev->data==root->data){
      return false;
    }
    else{
    prev->sibs=root;
    return true;
    }
}


string CTree::toString(){
  if(kids!=nullptr){
    return string(1,this->data)+"\n"+kids->toString();
  }
  else{
    return string(1,this->data)+"\n";
  }
  if(sibs!=nullptr){
    return string(1,this->data)+"\n"+sibs->toString();
  }
  else{
    return string(1,this->data)+"\n";
  }
}

我真的不明白段错误来自哪里,我没有释放我的 toString 函数中的任何内存!

【问题讨论】:

  • 你需要在addChild里面分配内存。如果你取一个局部变量的地址,你会有一个悬空指针。
  • 我要做的另一件事是创建toString 方法const 以帮助捕获意外修改。

标签: c++ class tree segmentation-fault


【解决方案1】:

AddChild 内部,你正在这样做:

CTree temp(ch);
kids = &temp;

但是temp 是一个局部变量,所以一旦你从这个函数返回,它就会死掉,kids 不再指向一个有效的对象。

相反,您需要执行以下操作:

kids = new Ctree(ch);

你需要修复你正在做类似事情的所有功能。

【讨论】:

    【解决方案2】:

    addSibling 函数中的这两行是导致您的问题的原因:

    CTree temp(ch);
    return this->addSibling(&temp);
    

    第一行在addSibling 函数中定义了一个local 变量。这个变量的生命周期在函数返回时结束,对象被销毁。

    第二行调用将保存一个指向此局部变量的指针,该指针将在addSibling 返回时立即失效。

    稍后尝试取消引用此指针将导致未定义的行为

    一种可能的解决方案是动态分配temp

    CTree* temp = new CTree(ch);
    return this->addSibling(temp);  // Note lack of address-of operator & here
    

    你在addChild 有同样的问题

    CTree temp(ch);
    kids=&temp;
    

    这里你需要做例如:

    kids = new CTree(ch);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-04
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 2018-12-15
      相关资源
      最近更新 更多