在 GDB 中运行应用程序直到发生异常
Posted
技术标签:
【中文标题】在 GDB 中运行应用程序直到发生异常【英文标题】:Run an Application in GDB Until an Exception Occurs 【发布时间】:2010-11-10 01:38:11 【问题描述】:我正在开发一个多线程应用程序,我想使用 GDB 对其进行调试。
问题是,我的一个线程不断因消息而死:
pure virtual method called
terminate called without an active exception
Abort
我知道该消息的原因,但我不知道它出现在我的线程中的哪个位置。回溯真的很有帮助。
当我在 GDB 中运行我的应用程序时,它会在每次暂停或恢复线程时暂停。我希望我的应用程序继续正常运行,直到其中一个线程因该异常而死亡,此时一切都应该停止,以便我可以获得回溯。
【问题讨论】:
GDB 暂停时报告什么信号?您应该能够运行类似handle SIGUSR1 pass noprint nostop
的命令
【参考方案1】:
您可以尝试使用“catchpoint” (catch throw
) 在生成异常的位置停止调试器。
以下来自 gdb 手册的 excerpt 描述了 catchpoint 功能。
5.1.3 设置捕获点
您可以使用捕获点使调试器停止某些类型的程序事件,例如 C++ 异常或共享库的加载。使用 catch 命令设置捕获点。
捕捉事件
当事件发生时停止。事件可以是以下任何一种:
投掷
抛出 C++ 异常。
赶上
捕获 C++ 异常。
执行
对 exec 的调用。这目前仅适用于 HP-UX。
分叉
调用 fork。这目前仅适用于 HP-UX。
vfork
对 vfork 的调用。这目前仅适用于 HP-UX。
加载或加载库名
任何共享库的动态加载,或库 libname 的加载。这目前仅适用于 HP-UX。
卸载或卸载库名
卸载任何动态加载的共享库,或卸载库 libname。这目前仅适用于 HP-UX。
tcatch 事件
设置一个只为一站启用的捕获点。捕获点在第一次捕获事件后自动删除。
使用info break
命令列出当前的捕获点。
目前在 GDB 中对 C++ 异常处理(catch throw 和 catch catch)有一些限制:
如果您以交互方式调用函数,GDB 通常会在函数完成执行后将控制权返回给您。但是,如果调用引发异常,调用可能会绕过将控制权返回给您的机制,并导致程序中止或继续运行,直到遇到断点、捕获 GDB 正在侦听的信号或退出。即使您为异常设置了捕获点,情况也是如此;在交互式调用中禁用异常捕获点。
您不能以交互方式引发异常。
您不能以交互方式安装异常处理程序。
有时 catch 不是调试异常处理的最佳方法:如果您需要确切知道异常在哪里引发,最好在调用异常处理程序之前停止,因为这样您可以在任何展开之前看到堆栈发生。如果您改为在异常处理程序中设置断点,则可能不容易找出引发异常的位置。
要在调用异常处理程序之前停止,您需要了解一些实现知识。在 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);
要让调试器在任何堆栈展开之前捕获所有异常,请在 __raise_exception 上设置断点(请参阅断点;观察点;和异常部分)。
使用取决于 id 值的条件断点(请参阅中断条件部分),您可以在引发特定异常时停止程序。当引发任何异常时,您可以使用多个条件断点来停止程序。
【讨论】:
您还可以指定要捕获的异常类型,例如catch throw std::runtime_exception
.【参考方案2】:
FWIW,显然,在 gcc 4.1 中,相应的函数名称已更改,必须在此函数中设置断点。
__cxa_pure_virtual
【讨论】:
【参考方案3】:在 __pure_virtual 上设置断点
【讨论】:
在@JeffreyHill 的回答中,它现在被称为 __cxa_pure_virtual 。我不知道如何自己检查,所以我不想编辑答案。我不打算投反对票,但现在答案可能是错误的,应该由知道什么是正确的人编辑。【参考方案4】:只有以下一个适用于 gdb 8.3:
break _Unwind_RaiseException
“catch throw”或“break __cxx_throw”对我不起作用。
【讨论】:
第二个,gdb 8.3 + clang 8。以上是关于在 GDB 中运行应用程序直到发生异常的主要内容,如果未能解决你的问题,请参考以下文章