gdb允许人们在抛出异常时捕获异常,并在捕获异常时捕获异常。但有时抛出异常的行没有符号,或者在异常处理期间触发断点。如何检查当前异常的值?
答案 0 :(得分:8)
<强>更新强>
以下是GDB手册中的一些信息
目前C ++异常处理存在一些限制(catch 在gdb中抛出并捕获catch:
如果以交互方式调用函数,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
通过这种方式,您可以在抛出异常之前获得断点,然后在捕获异常时获取断点,然后您可以遍历堆栈以获取有关正在发生的事情的更多信息。即使您处于另一个断点,您也应该能够向上走(使用向上或向下)以获得可以看到异常的帧。
答案 1 :(得分:6)
早期的答案在撰写时(2013年)是正确的,但从那以后gdb和libstdc ++已经改变。
libstdc ++现在有一些钩子让gdb与异常系统更好地交互。特别是,现在有足够的信息暴露给gdb,以便为用户提供$_exception
便利变量。此变量保存抛出的异常。它仅在捕获异常的地方有效;您可以停止使用catch catch
。
有关详细信息,请参阅the page from the manual。
答案 2 :(得分:3)
简短的回答:你不能,因为大多数异常处理工作是在你的程序之外完成的,因此不在gdb的范围之内。
解释答案:
有时抛出异常的行没有符号
如果您正在调试的二进制文件没有调试符号,那么二进制文件可能已被删除,您根本无法找到任何关于任何类型/值的内容。
如何检查当前异常的值?
我认为你在这里假设一个异常是gdb可以检查的语言特性;实际上,C ++中的一个例外是C ++作为语言,libc ++和ABI的特性组合。甚至可能存在多个活动当前异常。
像UpAndAdam指出的那样你可以在一个带有类型说明符的catch块中设置一个断点,然后检查那个元素,但我怀疑你的问题是在你找到“catch(...)”的情况下。在这些情况下,除非您深入研究异常处理的实现,否则您将无法了解当前的异常。
有一个非常简短和不完整的描述,我们可以说抛出异常:
现在,很难谈论细节,因为很多异常处理取决于你的工具链(编译器,平台,架构,libc ++等),但在大多数情况下,“catch(...)”甚至不会收到原始异常作为参数。在任何情况下,以某种方式回答你的问题:在gcc与gnu的libc ++你可以尝试这样的事情:
无论如何,您可能需要花费大量时间来了解如何在您的平台中实现异常处理。如果你想阅读更多关于异常处理的内容,我过去花了一些时间写了关于@ http://monoinfinito.wordpress.com/series/exception-handling-in-c/主题的文章。它不是官方来源,但它确实链接到处理异常所涉及的每个部分的规范。