c++ - 尝试递增 std::map 迭代器时出现 SIGBUS

标签 c++ c++98

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

通过跟踪,我发现有问题的方法从提到的映射中删除了元素(间接地,通过调用调用其他方法的其他方法等等......),所以我怀疑问题是在删除其元素的同时遍历 map

我一直在寻找正确的方法来迭代 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;
  }
}

代码引用自 How to remove from a map while iterating 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
}

由于删除是由其他方法执行的,所以我无法区分元素是否已被删除(除非我返回 bool 值或类似值)。 这可能不安全吗?

最佳答案

Is the following code snippet equivalent to the above one, in terms of safety?

不,当然不是,在将它传递给 map.erase() 之后,您不能增加 it,因为该迭代器已因该调用而失效。区别在于:

 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++;
}

关于c++ - 尝试递增 std::map 迭代器时出现 SIGBUS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47699537/

相关文章:

c++ - 如何将数组的偶数和奇数相加

c++ - 全局外部常量说明

c++ - 浮点异常问题

c++ - 将 std::vector<bool> 添加到容器变体

c++ - 带有模板参数的模板特化

java - 如何使用 jni 将数据从 java InputStream 移动到 C++ 中的 char *?

c++ - 创建不带参数的 sigc::slot

c++ - 寻找一种更好的方法来表示无符号字符数组

c++ - 用 C++11 编译比用 C++98 慢吗?

c++ - std::size_t 与 size_type 作为参数和函数返回类型