我在调试分段错误时遇到了问题。我很感谢提示如何在问题上缩小范围。访问boost :: unordered_multimap或结构体时偶尔出现分段错误
时的迭代器尝试访问一个结构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
来查找其recT
与恢复时间(double recoverTime
)相匹配的Infection
。 (对于那些不值得进入的原因,它不是作为权宜之计,我使用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从回溯读取
“#0 0x0000000100001d50在Host.cpp主持人::恢复(此= 0x100530d80,S = 0,recoverTime = 635.91148029170529):317”
我不知道什么有用我可以在这里提取信息。
更新2
我的carriage.erase(it)
后添加一个break;
。这工作。
你的调试环境是什么? Eclipse通常擅长在发生故障时暂停执行,以便检查调用堆栈。您是否尝试过每次通过循环打印与迭代器相关联的某个值来进行printf调试?你有没有检查ret.first和ret.last的值是否合理? – Bruce 2010-05-18 22:20:40
我使用gdb,但显然不够好!将调查ret.first和ret.last。 – Sarah 2010-05-18 22:25:05