首页 > 解决方案 > 为什么从 std::list 中擦除会给我一个段错误?

问题描述

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

这是设置_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);

任何帮助是极大的赞赏。

标签: c++listsegmentation-fault

解决方案


推荐阅读