首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIGBUS试图增加std::map迭代器

SIGBUS试图增加std::map迭代器
EN

Stack Overflow用户
提问于 2017-12-07 16:28:27
回答 2查看 181关注 0票数 0

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

通过压缩跟踪,我发现该方法从所提到的映射中删除元素(indireclty,通过调用调用其他方法等的其他方法等等),因此我怀疑问题是在删除其元素时迭代映射。

我一直在寻找一种正确的方法来安全地遍历一个std::map和删除条目,并且我发现了以下内容:

代码语言:javascript
复制
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;
  }
}

引用自How to remove from a map while iterating it?的代码

我对此有几个问题:

考虑到迭代器在任何情况下都会增加,是否有必要区分是否删除元素?

在安全性方面,下面的代码片段是否等同于上面的代码片段?

代码语言:javascript
复制
for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
  if (must_delete)
  {
    m.erase(it);
  }
  it++;
}

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

代码语言:javascript
复制
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
}

由于删除是由其他方法/s执行的,所以如果元素已被删除或没有删除,我将无法区分(除非我返回一个布尔值或类似值)。这可能不安全吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-07 16:37:28

在安全性方面,下面的代码片段是否等同于上面的代码片段?

不,当然不是,您不能在将it传递给map.erase()之后增加它,因为该迭代器被该调用所失效。不同之处是:

代码语言:javascript
复制
 map.erase(it++);

在逻辑上相当于:

代码语言:javascript
复制
iterator tmp = it;
++it;
map.erase( tmp );

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

考虑到这一守则:

代码语言:javascript
复制
while(it != myMap.end() {
  if(somethingHappens())
    doSomethingThatMightDeleteMapElements(); // this can (or not) delete 'myMap' elements.
  it++; // The error occurs here
}

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

代码语言:javascript
复制
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++;
}
票数 2
EN

Stack Overflow用户

发布于 2017-12-07 16:41:20

由于删除是由其他方法/s执行的,所以我无法区分元素是否已被删除(除非我返回布尔值或类似的值)。

你当然可以。在调用doSomethingThatMightDeleteMapElements之前保持映射的大小。在调用doSomethingThatMightDeleteMapElements之后获取映射的大小。然后根据它们是否相等采取适当的行动。

代码语言:javascript
复制
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
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47699537

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档