在投掷时拦截std :: out_of_range错误

时间:2018-04-11 05:45:34

标签: c++11 exception-handling

给出基本代码:

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 throwgdb会在throw处将控制权交还给我,所以我可以轻松追踪错误的位置,而不是捕获的位置。是否有C++11gcc特定的机制,我可以模仿gdb正在做什么?

注意,有this question,但那是信号错误;它对我来说对普通的throw没有用。

1 个答案:

答案 0 :(得分:2)

boost::exception例如将堆栈跟踪存储在初始投掷上。 std:: exception没有,因此在展开之前您无法看到堆栈跟踪。重新抛出嵌套在类似Boost异常之类的原始异常将为您提供堆栈跟踪,但仍然只能创建嵌套异常。

没有办法解决这个问题,你所能做的就是安装一个自定义处理程序来捕获异常,因为它们被抛出,但这是非常多的编译器和运行时特定的。基本上,您将使用设计用于调试的区域。

无论如何,你应该真正关心你捕获的异常的堆栈跟踪。在这种情况下让异常崩溃更好,并利用Breakpad或类似方法创建完整的崩溃转储,以便进行后期分析,不仅可以完整堆栈跟踪,还可以完整堆栈内容。只捕获您打算恢复的异常,其他一切只是错误隐藏(即使不是故意)并使调试更难。