【问题标题】:Can a thrown exception be accessed in a C++ catch(...) block可以在 C++ catch(...) 块中访问抛出的异常吗
【发布时间】:2012-01-12 19:38:56
【问题描述】:

我已将 GDB 附加到当前位于 catch(...) 块内的进程。

是否有已知的技术可以访问抛出的异常?

有问题的程序是 gcc/x86-64 二进制文件,但我也对其他版本感到好奇。

【问题讨论】:

  • 是的,当然它仍然存在,但是你不知道它的类型,你打算怎么处理它?
  • 嗯,也许你可以在活动异常对象上做一些 RTTI。检查您的 ABI 文档;它可能只是描述类似的东西......

标签: c++ gcc exception-handling gdb


【解决方案1】:

正如你所说,你可以重新抛出它,所以你可以在另一个 try/catch 块中重新抛出它,其中包含更具体的子句以提取异常(如果你愿意,还可以再抛出另一个 ...)。您甚至可以在另一个函数中执行此操作,以便集中处理异常。

编辑:我误解了gdb 在您的问题中的重要性,但您可以应用我描述的想法。创建一个重新抛出异常的函数,您可以在其中设置断点:

void
helper()
{
    try {
        throw;
    } catch (int i) {
        // anything that won't get optimized away
        volatile int j = i;  // breakpoint here
    }
}

然后在gdb 中执行call helper()。我刚刚对此进行了测试以确保它有效。

进一步编辑:如果您的字面意思是 我正在 gdb 下运行一个程序 现在并且在您确定不能退出之前不会退出 gdb得到异常,那么是时候查看eh_throw.cc 和gcc 源中的朋友了。 __cxa_rethrow 开头为:

  __cxa_eh_globals *globals = __cxa_get_globals ();
  __cxa_exception *header = globals->caughtExceptions;

你必须检查所有这些结构,才能弄清楚里面埋着什么。

【讨论】:

    【解决方案2】:

    我还没有对此进行测试 - 但异常(或至少是指向它的指针)可能应该在堆栈中靠近头部的某个地方。我猜确切的位置和格式取决于实现,但是您应该能够将堆栈的这个区域中的不同地址转换为您的异常类型(或至少转换为 std::exception)并查看是否获得有意义的结果。

    【讨论】:

    • 异常不能在堆栈上,因为它必须在堆栈回退期间持续存在。大多数实现都有一些特殊的、独立的区域来分配它们,但是这个区域不能从 C++ 访问。
    • @James - 但是指向它的指针可能在堆栈上。异常的副本可以在堆栈上 - 您可以使用以下代码:'catch (std::exception ex)',它复制异常。 '...' 不太可能以这种方式实现,但有可能
    • 我从来没有见过一个指向它的指针在堆栈上的实现。 catch 的语义或多或少是函数的语义:如果按值捕获,则获得本地副本;如果您通过引用捕获,对异常的引用,并且如果您 catch(...),则运行时不会比调用没有 args 的函数时更多地放在堆栈上。
    • 好吧,正如 OP 所说,假设堆栈上有东西是合理的,因为它可以被重新抛出。但你是对的。这不是强制性的。它可以通过其他方式实现。
    • @Asaf:它是从 James Kanze 提到的“特殊区域”重新抛出的。请注意,您使用 throw; 重新抛出 - 它不需要异常的副本。
    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 2012-02-20
    相关资源
    最近更新 更多