关键词:breakpoint、catchpoint、catch、throw、assert、load/unload、fork/vfork/exec、syscall、signal等等。
Breakpoints能让程序执行到后暂停流程,包括Breakpoints、Watchpoints、Catchpoints。
Catchpoints是一种特殊的Breakpoints,当某种特殊的事件产生后停止程序执行。
除了设置Catchpoints,其他对Catchpoints的管理方式类似于Breakpoints。
测试环境:Ubuntu 16.04, GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1。
1. 设置Catchpoints
《Breakpoints, Watchpoints, and Catchpoints》、《Setting catchpoints》、《Signals》、《Stopping and Starting Multi-thread Programs》。
在gdb中通过help catch可以看出支持哪些种类的events:
catch assert -- Catch failed Ada assertions catch catch -- Catch an exception catch exception -- Catch Ada exceptions catch exec -- Catch calls to exec catch fork -- Catch calls to fork catch load -- Catch loads of shared libraries catch rethrow -- Catch an exception catch signal -- Catch signals by their names and/or numbers catch syscall -- Catch system calls by their names and/or numbers catch throw -- Catch an exception catch unload -- Catch unloads of shared libraries catch vfork -- Catch calls to vfork
catch/throw都是捕获exception,但是区别是:throw是The throwing of a C++ exception,catch是The catching of a C++ exception。
通过info break可以查看设置的Catchpoints。
有时候通过catch捕获到异常,此时已经进入异常处理函数中,有可能栈并不能指示确切发生了什么。
这时候可以通过在__raise_exception()打断点,能看到更直接的现场。
2. 构造Catchpoints
2.1 catch和throw
C++的异常有很多,下面以bad_function_call为例。
对如下程序编译:g++ -o bad_function_call bad_function_call.cc -g -Wall --std=c++11。
// bad_function_call example #include <iostream> // std::cout #include <functional> // std::function, std::plus, std::bad_function_call int main () { std::function<int(int,int)> foo = std::plus<int>(); std::function<int(int,int)> bar; try { std::cout << foo(10,20) << ' '; std::cout << bar(10,20) << ' '; } catch (std::bad_function_call& e) { std::cout << "ERROR: Bad function call "; } return 0; }
在gdb中设置catch catch和catch throw之后结果如下:
(gdb) r Starting program: /home/al/temp/catch/bad_function_call 30 Catchpoint 2 (exception thrown), 0x00007ffff7ae28bd in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (gdb) bt full #0 0x00007ffff7ae28bd in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 No symbol table info available. #1 0x00007ffff7b0b8b2 in std::__throw_bad_function_call() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 No symbol table info available. #2 0x0000000000400f44 in std::function<int (int, int)>::operator()(int, int) const (this=0x7fffffffdb00, __args#0=10, __args#1=20) at /usr/include/c++/5/functional:2266 No locals. #3 0x0000000000400c74 in main () at bad_function_call.cc:11 foo = {<std::_Maybe_unary_or_binary_function<int, int, int>> = {<std::binary_function<int, int, int>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x470, _M_const_object = 0x470, _M_function_pointer = 0x470, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x470, this adjustment 4295032831}, _M_pod_data = "p 04 00 00 00 00 00 00377377 00 00 01 00 00"}, _M_manager = 0x40104b <std::_Function_base::_Base_manager<std::plus<int> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation)>}, _M_invoker = 0x400ff3 <std::_Function_handler<int (int, int), std::plus<int> >::_M_invoke(std::_Any_data const&, int&&, int&&)>} bar = {<std::_Maybe_unary_or_binary_function<int, int, int>> = {<std::binary_function<int, int, int>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x2, _M_const_object = 0x2, _M_function_pointer = 0x2, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x2, this adjustment 4199101}, _M_pod_data = "