【发布时间】:2013-04-25 03:51:06
【问题描述】:
gdb 允许人们在异常被抛出和被捕获时捕获它们。但有时抛出异常的行没有符号,或者在异常处理期间触发了断点。如何检查当前异常的值?
【问题讨论】:
标签: c++ debugging exception gdb inspection
gdb 允许人们在异常被抛出和被捕获时捕获它们。但有时抛出异常的行没有符号,或者在异常处理期间触发了断点。如何检查当前异常的值?
【问题讨论】:
标签: c++ debugging exception gdb inspection
早期的答案在编写时(2013 年)是正确的,但从那时起 gdb 和 libstdc++ 发生了变化。
libstdc++ 现在有一些钩子可以让 gdb 更好地与异常系统交互。特别是,现在有足够的信息让 gdb 为用户提供$_exception 便利变量。该变量保存被抛出的异常。它仅在捕获异常的确切位置有效;您可以停止使用catch catch。
【讨论】:
更新
以下是 GDB 手册中的一些信息
目前 C++ 异常处理有一些限制(catch 在 gdb 中抛出和捕获):
如果您以交互方式调用函数,gdb 通常会将控制权返回给 当函数完成执行时。如果调用引发 异常,但是,调用可能会绕过返回的机制 控制权并导致您的程序中止或简单地 继续运行直到遇到断点,捕获 gdb 的信号 正在监听或退出。即使您设置了一个 异常的捕获点;异常捕获点被禁用 在交互式通话中。您不能以交互方式引发异常。 您不能以交互方式安装异常处理程序。有时抓 不是调试异常处理的最佳方法:如果您需要知道 确切地在哪里引发异常,最好在发生异常之前停止 异常处理程序被调用,因为这样你可以看到堆栈 在任何平仓发生之前。如果你在一个 相反,异常处理程序可能不容易找到 引发了异常。
要在调用异常处理程序之前停止,您需要一些 实施的知识。在 gnu C++ 的情况下,异常 通过调用名为 __raise_exception 的库函数引发 具有以下 ANSI C 接口:
/* addr is where the exception identifier is stored. id is the exception identifier. */ void __raise_exception (void **addr, void *id); To make the debugger catch all exceptions before any stack unwinding takes place,在 __raise_exception 上设置断点(请参阅断点;观察点; 和例外)。
说的是
这取决于代码和您在堆栈中的位置。如果你真的捕获了异常,如下所示:
try { .... } catch (std::exception &e) {
//do stuff
}
您可以尝试打印e.what(),或者查看异常的成员。如果你只是把它当作 (...) 那么我不确定你能收集到什么。
如果您真的想遵循整个流程,您可以做的另一件事是在 gdb 中捕获 'throw' 并捕获 'catch'。
gdb> catch catch
gdb> catch throw
这样,您将在抛出异常之前和捕获异常时立即获得断点,然后您可以遍历堆栈以获取有关正在发生的事情的更多信息。即使您处于另一个断点,您也应该能够向上走堆栈(使用向上或向下)以获取异常可见的帧。
【讨论】:
简短的回答:您不能,因为大多数异常处理工作都是在您的程序之外完成的,因此不在 gdb 的范围内。
解释答案:
有时抛出异常的行没有符号
如果您正在调试的二进制文件没有调试符号,则该二进制文件可能已被剥离,您将无法找到任何关于任何类型/值的任何内容。
如何检查当前异常的值?
我认为您在这里假设异常是 gdb 可以检查的语言功能;事实上,C++ 中的一个例外是 C++ 作为一种语言、libc++ 和 ABI 的特性的组合。甚至可能有不止一个活动的当前异常。
就像 UpAndAdam 指出的那样,您可以使用类型说明符在 catch 块中设置断点,然后检查该元素,但我怀疑您的问题在于您发现“catch (...)”的情况。在这些情况下,除非您深入研究异常处理的实现,否则您将无法对当前异常了解很多。
通过非常简短且不完整的描述,我们可以说抛出异常:
现在,很难谈论细节,因为很多异常处理取决于您的工具链(编译器、平台、架构、libc++ 等),但在大多数情况下,“catch (...)”甚至不会收到原始异常作为参数。无论如何,要以某种方式回答您的问题:在 gcc 和 gnu 的 libc++ 中,您可以尝试这样的事情:
无论如何,您可能需要花费大量时间来了解异常处理是如何在您的平台中实现的。如果您想了解更多关于异常处理的信息,我在过去花了一些时间写了关于 @http://monoinfinito.wordpress.com/series/exception-handling-in-c/ 的主题。它不是官方来源,但它确实包含处理异常所涉及的每个部分的规范的链接。
【讨论】: