在GDB中引发特定exceptiontypes时如何中断?
根据文档,我可以通过使用条件断点来打破特定的exceptiontypes。 不过,条件的语法对我来说并不是很清楚:
condition bnum <expression>
看看expression式语法,我认为这是我需要的模式:
{type} addr
但是,我不知道我应该通过addr
参数。 我尝试了以下内容:
(gdb) catch throw (gdb) condition 1 boost::bad_function_call *
但它不起作用(gdb中断所有exceptiontypes)。
谁能帮忙?
更新
我也试过@亚当的build议,但它会产生一个错误信息:
(gdb) catch throw boost::bad_function_call Junk at end of arguments.
没有boost::
namespace:
(gdb) catch throw bad_function_call Junk at end of arguments.
解决方法
破坏bad_function_call
的构造函数。
编辑
该文档build议,只要引发types<exceptname>
的exception, catch throw <exceptname>
就可以被破坏; 然而,这在实践中似乎并不奏效。
(gdb) help catch Set catchpoints to catch events. Raised signals may be caught: catch signal - all signals catch signal <signame> - a particular signal Raised exceptions may be caught: catch throw - all exceptions, when thrown catch throw <exceptname> - a particular exception, when thrown catch catch - all exceptions, when caught catch catch <exceptname> - a particular exception, when caught Thread or process events may be caught: catch thread_start - any threads, just after creation catch thread_exit - any threads, just before expiration catch thread_join - any threads, just after joins Process events may be caught: catch start - any processes, just after creation catch exit - any processes, just before expiration catch fork - calls to fork() catch vfork - calls to vfork() catch exec - calls to exec() Dynamically-linked library events may be caught: catch load - loads of any library catch load <libname> - loads of a particular library catch unload - unloads of any library catch unload <libname> - unloads of a particular library The act of your program's execution stopping may also be caught: catch stop C++ exceptions may be caught: catch throw - all exceptions, when thrown catch catch - all exceptions, when caught Ada exceptions may be caught: catch exception - all exceptions, when raised catch exception <name> - a particular exception, when raised catch exception unhandled - all unhandled exceptions, when raised catch assert - all failed assertions, when raised Do "help set follow-fork-mode" for info on debugging your program after a fork or vfork is caught. Do "help breakpoints" for info on other commands dealing with breakpoints.
当gdb命令“catch throw”失败时,试试这个解决方法:
(用Linux g ++ 4.4.5 / gdb 6.6testing)
1 /在程序的任何位置添加此代码以进行debugging:
#include <stdexcept> #include <exception> #include <typeinfo> struct __cxa_exception { std::type_info *inf; }; struct __cxa_eh_globals { __cxa_exception *exc; }; extern "C" __cxa_eh_globals* __cxa_get_globals(); const char* what_exc() { __cxa_eh_globals* eh = __cxa_get_globals(); if (eh && eh->exc && eh->exc->inf) return eh->exc->inf->name(); return NULL; }
2 /在gdb中,您将可以使用以下方式过滤exception:
(gdb) break __cxa_begin_catch (gdb) cond N (what_exc()?strstr(what_exc(),"exception_name"):0!=0)
其中N是断点编号,exception_name是我们希望中断的exception的名称。
从我从这里的问题中了解到,当你的应用程序抛出一个特定的exceptionboost::bad_function_call
时候,你想中断。
$> gdb /path/to/binary (gdb) break boost::bad_function_call::bad_function_call() (gdb) run --some-cli-options
所以当临时对象boost::bad_function_call
被构造为throw
, GDB将爆发!
我已经testing了这个,它确实工作。 如果你正确地知道构造exception对象的方式,那么你可以在特定的构造函数上设置断点,否则如下面的例子所示,你可以省略参数原型列表, gdb
将在所有不同的风格上设置断点构造函数。
$ gdb /path/to/binary (gdb) break boost::bad_function_call::bad_function_call Breakpoint 1 at 0x850f7bf: boost::bad_function_call::bad_function_call. (4 locations) (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <MULTIPLE> 1.1 y 0x0850f7bf in boost::bad_function_call::bad_function_call() at /usr/include/boost/function/function_base.hpp:742 1.2 y 0x0850fdd5 in boost::bad_function_call::bad_function_call(boost::bad_function_call const&) at /usr/include/boost/function/function_base.hpp:739 1.3 y 0x0863b7d2 <boost::bad_function_call::bad_function_call()+4> 1.4 y 0x086490ee <boost::bad_function_call::bad_function_call(boost::bad_function_call const&)+6>
正如其他人已经提到的这个function在实践中不起作用。 但是,作为解决方法,你可以把条件catch throw
。 当抛出exception时,我们来__cxa_throw
函数。 它有几个指向exception类的参数,所以我们可以在其中的一个上设置条件。 在下面的示例gdb会话中,我将条件放在__cxa_throw
dest
参数上。 唯一的问题是dest
值(在这种情况下是0x80486ec)事先是未知的。 例如,可以通过首先运行gdb而无条件断点来知道。
[root@localhost ~]# [root@localhost ~]# gdb ./a.out GNU gdb (GDB) 7.2 Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /root/a.out...done. (gdb) catch throw Catchpoint 1 (throw) (gdb) condition 1 dest==0x80486ec No symbol "dest" in current context. (gdb) r warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context. warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context. warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context. Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x804a080, tinfo=0x8049ca0, dest=0x80486ec <_ZNSt13runtime_errorD1Ev@plt>) at ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc:68 68 ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc: No such file or directory. in ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc (gdb) bt #0 __cxxabiv1::__cxa_throw (obj=0x804a080, tinfo=0x8049ca0, dest=0x80486ec <_ZNSt13runtime_errorD1Ev@plt>) at ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc:68 #1 0x08048940 in main () at test.cpp:14 (gdb) ib Num Type Disp Enb Address What 1 breakpoint keep y 0x008d9ddb exception throw stop only if dest==0x80486ec breakpoint already hit 1 time (gdb)
更新
您还必须加载libstdc ++的debugging信息才能使用此解决方法。
另一种方法是在捕获点被触发时依赖可用的tinfo
参数,这是指向由typeid(type)
返回的对象的指针。
所以说如果我想要捕获exception的std::bad_alloc
被抛出,我可以这样做:
> p &typeid(std::bad_alloc) > $1 = (__cxxabiv1::__si_class_type_info *) 0x8c6db60 <typeinfo for std::bad_alloc> > catch throw if tinfo == 0x8c6db60
我想我可以回答有关设置有条件rest的部分。 我不会回答有关exception的问题,因为__raise_exception似乎不存在于g ++ 4.5.2(?)中
让我们假设你有下面的代码(我使用void来获得类似于gdb doc中的__raise_exception)
void foo(void* x) { } int main() { foo((void*)1); foo((void*)2); }
(2)你使用下面的命令
(gdb) break foo Breakpoint 1 at 0x804851c: file q.cpp, line 20. (gdb) condition 1 x == 2
如果你运行
(gdb) r
你会看到它停在第二个foo调用,但不是第一个
我认为,他们在文档中的含义是,你设置函数__raise_exception(非常依赖实现)
/* addr is where the exception identifier is stored id is the exception identifier. */ void __raise_exception (void **addr, void *id);
然后如上所述设置条件中断ID(你必须以某种方式确定什么是你的exceptiontypes的ID)。
不幸
(gdb) break __raise_exception
结果用(g ++ 4.5.2)
Function "__raise_exception" not defined.