【发布时间】:2013-03-15 23:53:46
【问题描述】:
我有一个程序,它遍历一个集合并替换一个元素,调用它自己直到它不能再继续下去,然后撤消它所做的并搜索下一个分支。
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;
}
我的程序似乎运行良好,并且在 my 系统上正常运行,但它在另一个系统上因分段错误而崩溃。 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)
但我不明白是什么原因造成的。我认为这与我如何使用迭代器有关,但我找不到它。可能出了什么问题?
【问题讨论】:
-
你想用这一切来完成什么?至少乍一看,根本不清楚你在做什么,或者你为什么要这样做。您已经根据树本身(或多或少)解释了您想要做什么,但没有解释所有这些应该完成的事情。
-
iterator n的目的是什么? -
不再使用了。
-
递归调用令人担忧。如果它使
it无效怎么办? -
您正在递归调用一个修改
std::set并循环从set1.begin()开始的整个集合的函数?你怎么能确定递归调用不会修改更早的东西,或者(更糟)与你在当前循环中的位置完全相同?如果循环不是以set1.begin()开头,那么确保不会那么困难,但是递归调用确实看起来很可疑,可能 遇到您的“危险迭代器”并删除it参考!
标签: c++ stl iterator segmentation-fault set