SIGBUS 尝试递增 std::map 迭代器时



我正在调试一个大的C++98应用程序,当一个方法尝试递增std::map::iterator时,我收到一个SIBGUS错误。

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

我一直在寻找迭代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()后,您无法增加因为该迭代器被该调用无效。区别在于:

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

最新更新