ошибка сегментации после двойного вызова функции toString - PullRequest
0 голосов
/ 21 апреля 2020

В настоящее время я работаю над написанием левого и правого класса братьев и сестер. Моя функция addSibling и моя функция toString не работают должным образом. Я буду sh упорядочивать братьев и сестер в возрастающих значениях ASCII и позволять моей функции addSibling возвращать false, когда символ внутри root является дубликатом. В моем заголовочном файле есть класс CTree, в котором публикуются c данные члена, дети, sibs, prev и объявления функций. Странная вещь, когда я создаю тест и пытаюсь вывести root с его дочерним элементом,

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!

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

Внутри AddChild вы делаете это:

CTree temp(ch);
kids = &temp;

, но temp является локальной переменной, поэтому, как только вы вернетесь из этой функции, она умрет, а kids - нет больше указывает на действительный объект.

Вместо этого вам нужно сделать что-то вроде этого:

kids = new Ctree(ch);

Вам нужно исправить все свои функции там, где вы делаете похожую вещь.

0 голосов
/ 21 апреля 2020

Эти две строки из функции addSibling приводят к вашей проблеме:

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

Первая строка определяет переменную local внутри функции addSibling. Время жизни этой переменной заканчивается, когда функция возвращается и объект уничтожается.

При вызове второй строки будет сохранен указатель на эту локальную переменную, указатель, который станет недействительным, как только 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...