繁体   English   中英

尝试增加std :: map迭代器时的SIGBUS

[英]SIGBUS when trying to increment a std::map iterator

我正在调试一个大型C ++ 98应用程序,并且当一种方法尝试增加std::map::iterator时,我得到了SIBGUS错误。

通过跟踪,我发现有问题的方法从提到的地图中删除了元素(indireclty,通过调用其他方法调用其他方法,依此类推...),因此我怀疑问题是要遍历地图同时删除其元素

我一直在寻找正确的方法来遍历std::map并安全地删除项目,而我发现了这一点:

for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
  if (must_delete)
  {
    m.erase(it++);    // or "it = m.erase(it)" since C++11
  }
  else
  {
    ++it;
  }
}

如何在迭代时从地图中删除 引用的代码

我对此有一些疑问:

考虑到在任何情况下都要增加迭代器,实际上是否有必要在删除元素之间进行区分?

就安全性而言,以下代码段是否等同于上述代码段?

for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
  if (must_delete)
  {
    m.erase(it);
  }
  it++;
}

产生SIGBUS的方法遵循以下模式:

std::map<..., ...>::iterator it = myMap.begin(); // myMap is an instance attribute and can be accessed by any class method.

while(it != myMap.end() {
  if(somethingHappens())
    doSomethingThatMightDeleteMapElements(); // this can (or not) delete 'myMap' elements.
  it++; // The error occurs here
}

由于删除是通过其他方法执行的,因此无法确定元素是否已删除(除非我返回布尔值或类似值)。 这可能不安全吗?

就安全性而言,以下代码段是否等同于上述代码段?

不,当然不能,将it传递给map.erase()后就无法增加it ,因为该迭代map.erase()该调用无效。 区别是:

 map.erase(it++);

在逻辑上等效于:

iterator tmp = it;
++it;
map.erase( tmp );

因此,在这种情况下, tmp无效,但it仍然有效。

考虑以下代码:

while(it != myMap.end() {
  if(somethingHappens())
    doSomethingThatMightDeleteMapElements(); // this can (or not) delete 'myMap' elements.
  it++; // The error occurs here
}

我认为唯一可行的方法是:

while(it != myMap.end() {
  if(somethingHappens()) {
    key_type key = it->first();
    doSomethingThatMightDeleteMapElements(); // this can (or not) delete          'myMap' elements.
    it = myMap.upper_bound( key );
  } else
     it++;
}

由于删除是通过其他方法执行的,因此我无法区分某个元素是否已删除(除非我返回布尔值或类似的值)。

当然可以。 在调用doSomethingThatMightDeleteMapElements之前,请保留地图的大小。 调用doSomethingThatMightDeleteMapElements之后,获取地图的大小。 然后根据是否相等采取适当的措施。

while(it != myMap.end() {
  size_t size_before = myMap.size();
  size_t size_after = size_before;
  if(somethingHappens())
  {
    doSomethingThatMightDeleteMapElements(); // this can (or not) delete myMap  elements.
    size_after = myMap.size();
  }

  if ( size_before != size_after )
  {
    // Be safe. Iterate from the start again.
    it = myMap.begin();
  }
  else
  {
    it++; // The error occurs here
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM