在stl集合中移除迭代器时出现分割错误

Segmentation fault when removing iterator in stl set

本文关键字:分割 错误 迭代器 stl 集合      更新时间:2023-10-16

我有一个程序,它遍历一个集合并替换一个元素,调用它自己,直到它不能继续下去,然后撤消它所做的并搜索下一个分支。

for(set<int>::iterator it=set1.begin();it!=set1.end();)
    {
        if(condition)
        {
            int l=*it;
            if(condition) set1.insert(l-rails[inuse]).first;
            set<int>::iterator it1=it;
            it++;
            set1.erase(it1);//this line has the problem
            //do other things, including a recursive call
            if(l>rails[inuse+1]+rails[inuse]) set1.erase(l-rails[inuse]);
            set1.insert(l);
        }
        else ++it;
    }

我的程序似乎运行良好,它在我的系统上正常工作,但它在另一个系统上由于分段错误而崩溃。valgrind检测到一个分段违反:

==3610== Process terminating with default action of signal 11 (SIGSEGV)
==3610==  Access not within mapped region at address 0x18
==3610==    at 0x4EA8039: std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) (in /usr/lib/libstdc++.so.6.0.17)
==3610==    by 0x402018: std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>, std::allocator<int> >::_M_erase_aux(std::_Rb_tree_const_iterator<int>) (stl_tree.h:1497)
==3610==    by 0x401A4A: std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>, std::allocator<int> >::erase(std::_Rb_tree_const_iterator<int>) (stl_tree.h:787)
==3610==    by 0x401586: std::set<int, std::less<int>, std::allocator<int> >::erase(std::_Rb_tree_const_iterator<int>) (stl_set.h:517)
==3610==    by 0x40104A: test() (fence8.cpp:32)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)
==3610==    by 0x40105E: test() (fence8.cpp:34)

但我不明白是什么原因造成的。我认为这与我使用迭代器的方式有关,但我找不到。哪里出了问题?

注意在迭代时不要更改set——如果其中一个递归调用删除了迭代器it所引用的元素,那么它将不再有效。考虑到每次递归调用从头遍历整个集合,这是一种可能性。