为什么从std :: list中擦除会给我一个段错误?

时间:2019-08-30 20:02:14

标签: c++ list segmentation-fault

我一直在函数解析系统中处理一些代码。它以树状结构来实现。目前,它只跟踪孩子,但我也想添加父母的信息。具体来说,我正在尝试添加一个指向父母的指针列表。但是,当我删除父母时,我需要从孩子中删除指针。当我尝试执行此操作时,会出现段错误。

这是设置_subnodes列表的构造函数。

EBUnaryTermNode(EBTermNode * subnode) : _subnode(subnode){
      _subnode->_parents.push_back(this);
    };

这里是析构函数,它调用擦除指向父对象的指针的函数。

virtual ~EBUnaryTermNode() {
      _subnode->eraseParent(this);
      if(_subnode->_parents.size() == 0 && _subnode->_holders.size() == 0)
        delete _subnode;
    };

这是删除指向父对象的指针的函数。

void eraseParent(EBTermNode * victim)
{
    std::list<EBTermNode *>::iterator it;
    for(it = _parents.begin(); it != _parents.end(); ++it)
         if(*it == victim)
         {
             std::cout << victim << std::endl;
             _parents.erase(it);
             break;
         }
}

EBUnaryTermNode类继承自此处定义的基类EBTermNode。

class EBTermNode
  {
  public:
    virtual ~EBTermNode(){};
    virtual EBTermNode * clone() const = 0;

    virtual std::string stringify() const = 0;
    virtual unsigned int substitute(const EBSubstitutionRuleList & /*rule*/) { return 0; }
    virtual int precedence() const = 0;
    friend std::ostream & operator<<(std::ostream & os, const EBTermNode & node)
    {
      return os << node.stringify();
    }
    void eraseParent(EBTermNode * victim)
    {
      std::list<EBTermNode *>::iterator it;
      for(it = _parents.begin(); it != _parents.end(); ++it)
        if(*it == victim)
        {
          std::cout << victim << std::endl;
          std::cout << *it << std::endl;
          _parents.erase(it);
          break;
        }
    }

    std::list<EBTermNode *> _parents;
    std::list<EBTerm *> _holders;
  };

在遇到段错误之前,它似乎可以工作一段时间(大约是cout语句的25倍)。

当我从调试器浏览堆栈时,得到以下信息:

Thread 1 "phase_field-dbg" received signal SIGSEGV, Segmentation fault.
0x00007fffe9adbf8d in __gnu_debug::_Safe_iterator_base::_M_singular (this=0x421010)
    at ../../../../../gcc-8.3.0/libstdc++-v3/src/c++11/debug.cc:403
403     ../../../../../gcc-8.3.0/libstdc++-v3/src/c++11/debug.cc: No such file or directory.
(gdb) up
#1  0x00007ffff77c14a2 in __gnu_debug::_Safe_sequence<std::__debug::list<ExpressionBuilder::EBTermNode*, std::allocator<ExpressionBuilder::EBTermNode*> > >::_M_invalidate_if<__gnu_debug::_Equal_to<std::__cxx1998::_List_const_iterator<ExpressionBuilder::EBTermNode*> > > 
    (this=0xa4e598, __pred=...)
    at /opt/moose/gcc-8.3.0/include/c++/8.3.0/debug/safe_sequence.tcc:48
48                  if (!__victim->_M_singular() && __pred(__victim->base()))
(gdb) 
#2  0x00007ffff77bda03 in std::__debug::list<ExpressionBuilder::EBTermNode*, std::allocator<ExpressionBuilder::EBTermNode*> >::_M_erase (this=0xa4e598, __position=...)             
    at /opt/moose/gcc-8.3.0/include/c++/8.3.0/debug/list:490
490             this->_M_invalidate_if(_Equal(__position));
(gdb) 
#3  0x00007ffff77b918c in std::__debug::list<ExpressionBuilder::EBTermNode*, std::allocator<ExpressionBuilder::EBTermNode*> >::erase (this=0xa4e598, __position=...)                
    at /opt/moose/gcc-8.3.0/include/c++/8.3.0/debug/list:503
503             return iterator(_M_erase(__position.base()), this);
(gdb) 
#4  0x00007ffff77b231c in ExpressionBuilder::EBTermNode::eraseParent (this=0xa4e590, 
    victim=0xa4e7a0)
    at /home/jason/Research/GBResearch/projects/moose/modules/phase_field/build/header_symlinks/ExpressionBuilder.h:95                                                              
95                _parents.erase(it);
(gdb) 
#5  0x00007ffff77b27ab in ExpressionBuilder::EBUnaryTermNode::~EBUnaryTermNode (
    this=0xa4e7a0, __in_chrg=<optimized out>)
    at /home/jason/Research/GBResearch/projects/moose/modules/phase_field/build/header_symlinks/ExpressionBuilder.h:155                                                             
155           _subnode->eraseParent(this);

非常感谢您的帮助。

0 个答案:

没有答案