包含所述对象

时间:2015-04-27 15:26:42

标签: c++ vector destructor

我对析构函数有点麻烦。在目前的状态下,它会产生一个段错误。请注意,析构函数只是实现的,并且从不在任何地方显式调用。无论断点位于何处,都会出现段错误。

这是析构函数:

Graph::~Graph() {

    while(!children.empty()) {

        for(vector<Graph*>::iterator itr = children.begin(); itr != children.end(); ++itr) {
            delete *itr;
        }
        children.clear();
        delete parent;
        delete tab;
    }
}

我也做了这样的变化,没有更好的结果:

Graph::~Graph() {

    while(!children.empty()) {

        for(unsigned i = 0; i < children.size(); i++)
        {
            delete children.at(i);
        }
        children.clear();
        delete parent;
        delete tab;
    }
}

这是类声明:

class Graph
{
    private :
            Graph*                      parent;
            vector<Graph*>              children;
            Board*                      tab;

    public :
                                    Graph(Board);
                                    Graph(Board, Graph*);
                                    ~Graph();
                void                AddNode(Board&);

          //      Graph&            BFS(Graph&); 
                Graph&              operator=(Graph source);
                vector<Graph*>&     getchildren();
                Graph*              getparent();
                Board*              gettab();
    };



class Board {

private :
            int**           tab;
            int             nbline;
            int             nbcolumn;
            Position        emptyspot;

public  :
                            Board();
                            Board(int, int, Play&);
                            Board(int, int);
                            Board(const Board&);
                            Board(int, int, ifstream&);
                            ~Board();
            void            setValue(Position&, int);
            void            setNbline(int m);
            void            setNbcolumn(int n);
            int             getValue(Position&);
            int             getNbline();
            int             getNbcolumn();
            int             getEmptyline();
            int             getEmptycolumn();
            void            setEmptySpot(Position&);
            Position&       getEmptySpot();

            Board&          operator=(Board& source);

        };


Board::~Board()
{
    for(int i = 0; i < this->nbline; i++)
    {
        delete tab[i];
    }
    delete tab;
}

我对调试器并不是很舒服且缺乏经验,所以我真的不知道如何正确使用它。此行的调用堆栈点是stl_vector.h:

  /**
   *  Returns a read-only (constant) iterator that points one past
   *  the last element in the %vector.  Iteration is done in
   *  ordinary element order.
   */
  const_iterator
  end() const _GLIBCXX_NOEXCEPT
  { return const_iterator(this->_M_impl._M_finish); }

我不知道这些行是什么意思诚实。

调用堆栈还在调试器中显示while循环行,其中注释:Graph :: ~Graphic(this = 0x90909090,__ in_chrg = optimize out)。我还指出行删除* itr的3倍(带有相同的音符)。

所以我的问题是,我如何破坏我的Graph对象?:'(

编辑:经过进一步的实验,当我删除在向量中添加内容的唯一linein代码时,段错误消失。这是方法。我将补充说,向量中的值总是相同的(不应该)。

void    Graph::AddNode(Board& tablo)
{
        Graph tmp(tablo, this);
        Graph* newChild = &tmp;
        children.push_back(newChild);  // if i commend this, no segfault
}

我不知道这是两个不同的问题还是push_back是析构函数故障的原因。我认为它是无关的,我预计segfault会消失(当然,如果树只有一个节点,析构函数也没有麻烦来破坏树。)

EDIT2:这段代码不会创建任何段错误,但它并没有真正破坏向量中的所有向量,对吧?我认为这不是因为擦除只会破坏指针而不是对象本身。

while(!children.empty()) {
        children.erase(children.begin(),children.end());
        delete parent;
        delete tab;
    }

此外,有了这个,有时程序似乎执行得很好但不会在执行结束时停止。 Debbuger似乎没有找到任何东西

编辑:as ask,Graph的复制构造函数:

Graph :: Graph(const Graph&amp; source){* this = source;}

Graph& Graph::operator=(Graph source)
{
     if(this!=source)
    {
        this->parent = source.parent;
        this->tab = source.tab;
//    this->seen = source.seen;


      while(!source.children.empty()) {

        for(unsigned i = 0; i<source.children.size(); i++) {
            this->children.at(i) = source.children.at(i);
            }
      }
    }

    return *this;
}

5 个答案:

答案 0 :(得分:4)

问题是:

delete parent;

您的循环正在强制Graph拥有其子级的语义。但是通过添加该行,您还可以添加Graph拥有其父级的语义。你不可能两种方式。这样,您的孩子将在删除您的孩子时删除您的父母。删除delete应解决您的问题。

更好的方法是根据成员变量明确表达所有权:

struct Graph {
    std::vector<std::unique_ptr<Graph>> children;
};

这样,即使不必编写析构函数,一切都会被正确删除!见Rule of Zero

答案 1 :(得分:0)

我同意@Barry那行

delete parent;

不应该在析构函数中存在。

此外,析构函数可以稍微清理一下。

您接到了电话

delete tab;

while循环内。无论是否有孩子,都应该在那里打电话。不应该吗?

您也可以完全删除while循环。

Graph::~Graph() {

   // Just loop over the children and delete them.
   // If there are no children, the loop is a no op.
   for(vector<Graph*>::iterator itr = children.begin(); itr != children.end(); ++itr) {
      delete *itr;
   }

   // No need for this.
   // The vector will be deleted anyway.
   // children.clear();


   // Delete tab regardless of the number of children.
   delete tab;
}

答案 2 :(得分:0)

AddNode函数似乎错了。当函数完成时,tmp对象将被销毁,然后向量中的指针变为无效,并在稍后调用delete时导致问题。

使用new代替。也许是这样的:

void    Graph::AddNode(Board& tablo)
{
    Graph* newChild = new Graph(tablo, this);
    children.push_back(newChild);
}

答案 3 :(得分:0)

我将总结我所做的修改及其后果。

我将析构函数更改为@R Sahu和Barry说。

Graph::~Graph() {

     for(vector<Graph*>::iterator itr = children.begin(); itr != children.end(); ++itr) {
      delete *itr;
   }
   delete tab;
}

我改变了addNodes,因为nielsen建议(DieterLücking也是如此):

void    Graph::AddNode(Board& tablo)
{
        Graph tmp(tablo, this);
         Graph* newChild = new Graph(tablo, this);
        children.push_back(newChild);
}

而且,正如Paul McKenzie所问,这是我的operator =和Graph的复制构造函数。

Graph::Graph(const Graph& source) : parent(source.parent), tab(source.tab) {

      while(!source.children.empty()) {

      for(unsigned i = 0; i<source.children.size(); i++) {
                this->children.at(i) = source.children.at(i);
                }
      }
}

Graph& Graph::operator=(Graph source)
{
    this->parent = source.parent;
    this->tab = source.tab;
//    this->seen = source.seen;

    return *this;
}

这让我想通了operator =不复制向量:'(

现在,如何执行。 Segfault仍在这里,但是callstack发生了很大变化。我在调用堆栈中只有2行,而不是5/6。 callstack告诉我

有问题
Board*           Graph::gettab(){return this->tab;}

当我这样做时,为了看看graph.children vector中的内容:

  for(vector<Graph*>::iterator itr = children.begin(); itr != children.end(); ++itr)
            {
              tmp = (*itr)->gettab();
              Board& test = *tmp;  // it's print(Board&) so i just create this. I'll create print(int**) later

              print(test);
 }

如果我将这些行放在注释中,则段错误仍然存​​在。 callstack在stl_iterator.h中引用了3行(你需要那些?)以及析构函数中的for循环和delete * itr行。

编辑:

@nielsen你问我的主人。

int main()
{
            int             lines, columns;
            Play            game;
            Play&           jeu = game;
            srand(time(NULL));

            cout << "+++++++++++++++++++++++++++++" << endl;
            cout << "+++     SOLVER            +++" << endl;
            cout << "+++++++++++++++++++++++++++++" << endl;
            cout << endl;
            cout << endl;


            cout << "Random Board \nLignes : ";
            cin >> lines;
            cout << "\n Colonnes : ";
            cin >> columns;

            Board           randomTab(lines, columns, jeu);

            print(randomTab);
            trace(randomTab);
            cout << "________________" << endl;

            Graph           tree(randomTab);  /// Call stack point to this !
            Board           temporary(randomTab);
            Board&          temp = temporary;
            Board*          tmp = NULL;
            bool            controls = false;

            vector<int> directions {72,75,77,80};

            for(vector<int>::iterator itr = directions.begin(); itr != directions.end(); ++itr)
            {
                temp = randomTab;
                controls = jeu.moves(temp,*itr);

                if(controls)
                {
                     cout << *itr << endl;
                     tree.AddNode(temp);
                     print(temp);
            //         trace(temp);
                     controls = false;
                }
            }

            cout << "__________________" << endl;
            vector<Graph*> children = tree.getchildren();

       /*     for(vector<Graph*>::iterator itr = children.begin(); itr != children.end(); ++itr)
            {
              tmp = (*itr)->gettab();
              Board& test = *tmp;

              print(test);
              cout << "test";
              trace(temporary);
            }*/


return 0;
}


Graph::Graph(Board source) : parent(NULL), tab(&source) {}  // constructeur pour racine

Graph::Graph(Board source, Graph* grap) : parent(grap), tab(&source) {} // constructeur pour nouvelle feuille


Graph::Graph(const Graph& source) : parent(source.parent), tab(source.tab) {  // constructeur par copie

      while(!source.children.empty()) {

      for(unsigned i = 0; i<source.children.size(); i++) {
                this->children.at(i) = source.children.at(i);
                }
      }
}

答案 4 :(得分:0)

有人问我董事会是如何创建的。在当前的用例中:

Board::Board(int m, int n, Play& jeu) : tab(new int*[m]), nbline(m), nbcolumn(n), emptyspot(n-1,m-1){

           int              x(1);

           for (int i = 0; i < m; ++i){
                tab[i] = new int[n];

                for(int j = 0; j < n; ++j) {
                    tab[i][j] = x; x++;}}

           tab[n-1][m-1]=0;
           x=0;

           while (x!=1000)
           {
            int numbers[] = { UP, DOWN, LEFT, RIGHT };
            int length = sizeof(numbers) / sizeof(int);
            int randomNumber = numbers[rand() % length];

            jeu.moves(*this, randomNumber);
            x++;
           }
        }

/// copy constructor
 Board::Board(const Board& origin): tab(NULL), nbline(origin.nbline), nbcolumn(origin.nbcolumn), emptyspot(origin.emptyspot)
        {
            this->tab = new int*[this->nbline];
            for (int i = 0; i < this->nbline; ++i)
            {
                this->tab[i] = new int[this->nbcolumn];
                for (int j = 0; j < this->nbline; ++j)
                {
                    this->tab[i][j] = origin.tab[i][j];
                }
            }
        }



Board::~Board()
{
    for(int i = 0; i < this->nbline; i++)
    {
        delete tab[i];
    }
    delete tab;
}



Board&              Board::operator=(Board& source)
{

    if (this != &source)
    {
            Position        pos(0,0);
            Position&       p=pos;

            this->setNbline(source.getNbline());
            this->setNbcolumn(source.getNbcolumn());
            this->setEmptySpot(source.getEmptySpot());

            for (int i =0; i < source.getNbline(); i++)
            {
                for(int j=0; j < source.getNbcolumn(); j++)
                {
                    p.setposition(i,j);
                    setValue(p,source.getValue(p));
                }
            }

    }