访问boost :: unordered_multimap或struct时不常出现分段错误

时间:2010-05-18 22:15:15

标签: c++ struct segmentation-fault

我在调试分段错误时遇到问题。我很欣赏如何缩小问题范围的提示。

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

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;

班级Host的每位成员都有一个InfectionMap carriage。恢复时间和关联的主机标识符保存在优先级队列中。当针对特定主机中的特定应变s的模拟中出现计划的恢复事件时,该程序会搜索该主机的carriage以查找Infection匹配的recT恢复时间(double recoverTime)。 (由于不值得进入的原因,使用recT作为InfectionMap的关键并不是权宜之计;应变s更有用,并且使用相同的共同感染应变是可能的。)

assert( carriage.size() > 0 );
pair<InfectionMap::iterator,InfectionMap::iterator> ret = carriage.equal_range( s );
InfectionMap::iterator it;
for ( it = ret.first; it != ret.second; it++ ) {
  if ( ((*it).second).recT == recoverTime ) { // produces seg fault
    carriage.erase( it );
  }
}

我在上面指定的行上收到“程序接收信号EXC_BAD_ACCESS,无法访问内存。原因:地址处的KERN_INVALID_ADDRESS ...”。 recoverTime很好,代码中的assert(...)没有被触发。

正如我所说,在成千上万次成功的恢复事件之后,这个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 );
  }
}

EXC_BAD_ACCESS错误现在出现在(*it).first来电,再次成功恢复数千次后。任何人都可以给我提示如何弄清楚这个问题是如何产生的?我正在尝试使用gdb。回溯中的第0帧读取

Host.cpp中的

“Host :: recover中的#0 0x0000000100001d50(此= 0x100530d80,s = 0,recoverTime = 635.91148029170529):317”

我不确定我可以在这里提取哪些有用的信息。


更新2

我在break;之后添加了carriage.erase(it)。这很有效。

2 个答案:

答案 0 :(得分:7)

如果我错了,请纠正我,但我敢打赌,删除无序多图中的项会使指向它的所有迭代器无效。试试“it = carriage.erase(it)”。你也必须做一些关于ret的事情。

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

在调用“carriage.erase(it)”之后突破循环的原因修复了错误是因为你停止尝试访问已删除的迭代器。

答案 1 :(得分:0)

使用gcc -g编译程序并在gdb下运行。当您遇到EXC_BAD_ACCESS崩溃时,您将进入gdb命令行。此时,您可以键入bt以获取回溯,这将显示您如何到达发生崩溃的位置。