C++ 访问boost::无序的_多重映射或结构时出现罕见的分段错误

C++ 访问boost::无序的_多重映射或结构时出现罕见的分段错误,c++,struct,segmentation-fault,C++,Struct,Segmentation Fault,我调试分段错误时遇到问题。我想知道如何缩小这个问题的范围 迭代器尝试访问结构的元素时会出现此错误,该结构定义为: struct Infection { public: explicit Infection( double it, double rt ) : infT( it ), recT( rt ) {} double infT; // infection start time double recT; // scheduled recovery time }; 这些结构保存在一

我调试分段错误时遇到问题。我想知道如何缩小这个问题的范围

迭代器尝试访问结构的元素时会出现此错误,该结构定义为:

struct Infection {
public:
  explicit Infection( double it, double rt ) : infT( it ), recT( rt ) {}
  double infT; // infection start time
  double recT; // scheduled recovery time
};
这些结构保存在一个特殊的结构中,
InfectionMap

typedef boost::unordered_multimap< int, Infection > InfectionMap;
我在上面指定的行上得到一个“程序接收信号EXC_BAD_ACCESS,无法访问内存。原因:KERN_无效_ADDRESS at ADDRESS…”。恢复时间很好,代码中的
断言(…)
没有触发

正如我所说,在数千次成功恢复事件之后,seg故障“随机”出现

你将如何着手弄清楚发生了什么?我很想知道哪些地方可能出错,以及如何进一步调查这个问题


更新

我在for循环中添加了一个新的断言和一个检查:

assert( carriage.size() > 0 );
assert( carriage.count( s ) > 0 );
pair<InfectionMap::iterator,InfectionMap::iterator> ret = carriage.equal_range( s );
InfectionMap::iterator it;
cout << "carriage.count(" << s << ")=" << carriage.count(s) << endl;
for ( it = ret.first; it != ret.second; it++ ) {
  cout << "(*it).first=" << (*it).first << endl; // error here
  if ( ((*it).second).recT == recoverTime ) {
    carriage.erase( it );
  }
}
assert(carries.size()>0);
断言(回车计数>0);
成对ret=托架。相等范围;
InfectionMap::迭代它;

cout用
gcc-g
编译程序,并在
gdb
下运行。当您获得一个
EXC\u BAD\u访问
崩溃时,您将进入gdb命令行。此时,您可以键入
bt
获取回溯,回溯将显示您是如何到达崩溃发生点的。

使用
gcc-g
编译程序,并在
gdb
下运行。当您获得一个
EXC\u BAD\u访问
崩溃时,您将进入gdb命令行。此时,您可以键入
bt
以获得回溯,回溯将显示您是如何到达崩溃发生点的。

如果我错了,请纠正我,但我敢打赌,删除无序多重映射中的项会使指向它的所有迭代器失效。试试“它=回车。擦除(它)”。你也得对ret做点什么

更新以答复您的最新更新:


调用“carries.erase(it)”后中断循环的原因修复了该错误,因为您停止尝试访问已擦除的迭代器。

如果我错了,请更正我,但我敢打赌,擦除无序多重映射中的项会使指向它的所有迭代器无效。试试“它=回车。擦除(它)”。你也得对ret做点什么

更新以答复您的最新更新:


调用“carries.erase(it)”后中断循环的原因修复了该错误,因为您停止尝试访问已擦除的迭代器。

您的调试环境是什么?Eclipse通常擅长在发生故障时停止执行,以便您可以检查调用堆栈。您是否尝试过通过每次通过循环打印与迭代器关联的值来进行printf调试?你检查过ret.first和ret.last的值了吗?我正在使用gdb,但显然不够好!将调查ret.first和ret.last。您的调试环境是什么?Eclipse通常擅长在发生故障时停止执行,以便您可以检查调用堆栈。您是否尝试过通过每次通过循环打印与迭代器关联的值来进行printf调试?你检查过ret.first和ret.last的值了吗?我正在使用gdb,但显然不够好!我会先调查,后调查,我已经盯着回溯跟踪一个小时了。它指向我上面提到的那条线。我会读更多关于如何破译地址的书。我已经盯着回溯追踪看了一个小时了。它指向我上面提到的那条线。我将阅读更多关于如何破译地址的内容。+1,除了
erase
不会返回下一个迭代器之外,您必须自己跟踪它。这一点,并且不要在for循环中不断增加它。@Noah和@avakar:如果特定恢复时间内总是只有一个感染,您的建议是否有效?(我已经确认seg故障出现时就是这种情况。)使用“it=carries.erase(it)”创建一个新的seg故障,该故障会立即出现在模拟中。@SB:你能解释一下为什么我不应该在for循环中增加它吗?@sarah-你只需要在不清除的情况下增加它。否则你已经在下一个了。我从未使用过无序的boost,因此我主要是根据Meyers如何描述实现来猜测。无序的_xxx是向量的向量或类似的东西,所以我希望它们的行为是这样的。例如:如果您正在迭代到一个目标,并且您删除了此处与此处之间的对象…此处移动,指向此处的指针不再指向此处。+1,除了
擦除
不返回下一个迭代器,你必须自己记录。这一点,不要在for循环中不断增加它。@Noah和@avakar:如果在特定的恢复时间内总是只有一种感染,你的建议有效吗?(我已经确认seg故障出现时就是这种情况。)使用“it=carries.erase(it)”创建一个新的seg故障,该故障会立即出现在模拟中。@SB:你能解释一下为什么我不应该在for循环中增加它吗?@sarah-你只需要在不清除的情况下增加它。否则你已经在下一个了。我从未使用过无序的boost,因此我主要是根据Meyers如何描述实现来猜测。无序的_xxx是向量的向量或类似的东西,所以我希望它们的行为是这样的。例如:如果你迭代到一个目的地,并且你在这里和那里之间删除了对象…那里移动了,你指向那里的指针不再指向那里。
assert( carriage.size() > 0 );
assert( carriage.count( s ) > 0 );
pair<InfectionMap::iterator,InfectionMap::iterator> ret = carriage.equal_range( s );
InfectionMap::iterator it;
cout << "carriage.count(" << s << ")=" << carriage.count(s) << endl;
for ( it = ret.first; it != ret.second; it++ ) {
  cout << "(*it).first=" << (*it).first << endl; // error here
  if ( ((*it).second).recT == recoverTime ) {
    carriage.erase( it );
  }
}