给出基本代码:
std::vector<int> foo(10);
foo.at[100] = 42;
这将按预期抛出std::out_of_range
,我机器上的默认行为是打印如下字符串:
在抛出'std :: out_of_range'的实例后调用终止what():vector :: _ M_range_check:__n(这是100)&gt; = this-&gt; size()(10)
如果我用try/catch
包装代码:
try {
foo.at[100] = 42;
} catch (std::out_of_range e) {
printf("Error at %s line %d\n", __FILE__, __LINE);
}
我当然可以找到出现问题的行,但如果代码有at
的数十次使用,我会这样做:
try {
functionThatCallsAtFromLotsOfPlaces();
} catch (std::out_of_range e) {
printf("Error at %s line %d\n", __FILE__, __LINE);
}
我只获取catch
的行号,而不是throw
。
另一方面,如果我在gdb
加载程序并输入catch throw
,gdb
会在throw
处将控制权交还给我,所以我可以轻松追踪错误的位置,而不是捕获的位置。是否有C++11
或gcc
特定的机制,我可以模仿gdb
正在做什么?
注意,有this question,但那是信号错误;它对我来说对普通的throw
没有用。
答案 0 :(得分:2)
boost::exception
例如将堆栈跟踪存储在初始投掷上。 std:: exception
没有,因此在展开之前您无法看到堆栈跟踪。重新抛出嵌套在类似Boost异常之类的原始异常将为您提供堆栈跟踪,但仍然只能创建嵌套异常。
没有办法解决这个问题,你所能做的就是安装一个自定义处理程序来捕获异常,因为它们被抛出,但这是非常多的编译器和运行时特定的。基本上,您将使用设计用于调试的区域。
无论如何,你应该真正关心你捕获的异常的堆栈跟踪。在这种情况下让异常崩溃更好,并利用Breakpad或类似方法创建完整的崩溃转储,以便进行后期分析,不仅可以完整堆栈跟踪,还可以完整堆栈内容。只捕获您打算恢复的异常,其他一切只是错误隐藏(即使不是故意)并使调试更难。