在抛出时拦截 std::out_of_range 错误
Intercepting an std::out_of_range error at throw time
给定基本代码:
std::vector<int> foo(10);
foo.at[100] = 42;
这将按预期抛出 std::out_of_range
,我的机器上的默认行为是打印如下字符串:
terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 100) >= this->size() (which is 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
-specific 中是否有一种机制,我可以在其中模拟 gdb
正在做什么?
注意,有this question,但那是信号错误;正常 throw
s 对我不起作用。
boost::exception
例如在初始抛出时存储堆栈跟踪。 std:: exception
没有,因此在展开之前您看不到堆栈跟踪。重新抛出嵌套在类似 Boost 异常中的原始异常将为您提供堆栈跟踪,但仍然只能创建嵌套异常。
没有办法解决这个问题,您所能做的就是安装一个自定义处理程序来捕获抛出的异常,但这在很大程度上是特定于编译器和运行时的。本质上,您将使用专为调试设计的端口。
无论如何,您真的不应该关心您捕获的异常的堆栈跟踪。在这种情况下,最好只让异常崩溃,并利用 Breakpad 或类似工具创建完整的故障转储,以进行事后分析,不仅具有完整的堆栈跟踪,而且堆栈内容完好无损。仅捕获您打算从中恢复的异常,其他一切都只是错误隐藏(即使不是故意的)并且使调试更加困难。
给定基本代码:
std::vector<int> foo(10);
foo.at[100] = 42;
这将按预期抛出 std::out_of_range
,我的机器上的默认行为是打印如下字符串:
terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 100) >= this->size() (which is 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
-specific 中是否有一种机制,我可以在其中模拟 gdb
正在做什么?
注意,有this question,但那是信号错误;正常 throw
s 对我不起作用。
boost::exception
例如在初始抛出时存储堆栈跟踪。 std:: exception
没有,因此在展开之前您看不到堆栈跟踪。重新抛出嵌套在类似 Boost 异常中的原始异常将为您提供堆栈跟踪,但仍然只能创建嵌套异常。
没有办法解决这个问题,您所能做的就是安装一个自定义处理程序来捕获抛出的异常,但这在很大程度上是特定于编译器和运行时的。本质上,您将使用专为调试设计的端口。
无论如何,您真的不应该关心您捕获的异常的堆栈跟踪。在这种情况下,最好只让异常崩溃,并利用 Breakpad 或类似工具创建完整的故障转储,以进行事后分析,不仅具有完整的堆栈跟踪,而且堆栈内容完好无损。仅捕获您打算从中恢复的异常,其他一切都只是错误隐藏(即使不是故意的)并且使调试更加困难。