【问题标题】:Intercepting an std::out_of_range error at throw time在抛出时拦截 std::out_of_range 错误
【发布时间】:2018-04-11 05:45:34
【问题描述】:

给定基本代码:

std::vector<int> foo(10);
foo.at[100] = 42;

这将按预期抛出std::out_of_range,并且我机器上的默认行为是打印如下字符串:

在抛出 'std::out_of_range' 的实例后调用终止 what(): vector::_M_range_check: __n (即 100) >= this->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-specific 中是否有一种机制,我可以在其中模拟 gdb 正在做什么?

注意,有this question,但那是针对信号错误的;对于普通的throws,它对我不起作用。

【问题讨论】:

  • 您对 std 异常无能为力。如果您愿意,您可以截取您自己的类抛出,以便它们记录 FILELINE 信息,但您确实需要一个宏来执行此操作。如果您从多个地方抛出相同的异常,这对于调试很有用,但也许最好抛出唯一的派生异常,并捕获基 - 捕获处的日志消息可以获得实际异常站点的类型名称.

标签: c++11 exception-handling


【解决方案1】:

boost::exception 例如在初始抛出时存储堆栈跟踪。 std:: exception 没有,因此在展开之前您看不到堆栈跟踪。重新抛出嵌套在类似 Boost 异常中的原始异常会为您提供堆栈跟踪,但仍仅取决于嵌套异常的创建。

没有办法解决这个问题,你所能做的就是安装一个自定义处理程序来捕获抛出的异常,但这在很大程度上是编译器和运行时特定的。本质上,您将使用专为调试而设计的端口。

无论如何,您真的不应该关心您捕获的异常的堆栈跟踪。在这种情况下,最好让异常崩溃,并利用 Breakpad 或类似工具创建完整的崩溃转储,以进行不仅完整的堆栈跟踪而且堆栈内容完好无损的 posthum 分析。仅捕获您打算从中恢复的异常,其他所有内容都只是错误隐藏(即使不是故意的)并使调试变得更加困难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多