程序员开发实例大全宝库

网站首页 > 编程文章 正文

深度C++:如何对throw打断点(c++ throw())

zazugpt 2024-09-01 07:56:02 编程文章 22 ℃ 0 评论

你的项目中有没有遇到过程序抛异常了,但你却不知道是在哪里抛出来的,项目太大太复杂了,对异常处理又不完善。

现在不用愁了,教你一个小方法,throw 本尊其实是函数__cxa_throw,这次你可以对其打断点了。

示例代码

#include <iostream>
using namespace std;
 
double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}
 
int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
     z = division(x, y);
     cout << z << endl;
   }catch (const char* msg) {
     cerr << msg << endl;
   }
 
   return 0;
}

编译、调试

$ g++ -g exception.cc  -o exception
$ gdb ./exception

Reading symbols from ./exception...
(gdb) b __cxa_throw
Breakpoint 1 at 0x1150
(gdb) r
Starting program: /mnt/e/doc/knowledge-git/bin/program/exception

Breakpoint 1, 0x00007ffff7e82750 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0x00007ffff7e82750 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00005555555552a9 in division (a=50, b=0) at exception.cc:8
#2  0x00005555555552f7 in main () at exception.cc:20

覆盖__cxa_throw例子

#include <iostream>
#include <dlfcn.h>
#include <execinfo.h>

using namespace std;


typedef void (*cxa_throw_type)(void *, void *, void (*) (void *));
cxa_throw_type orig_cxa_throw = 0;

void load_orig_throw_code()
{
    orig_cxa_throw = (cxa_throw_type) dlsym(RTLD_NEXT, "__cxa_throw");
}

extern "C"
void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *)) {
    printf(" ################ DETECT A THROWN !!!!! #############\n");
    if (orig_cxa_throw == 0)
        load_orig_throw_code();
    
    {
        static int throw_count = 0;
        void *array[10];
        size_t size;

        size = backtrace(array, 10);
        fprintf(stderr, "#### EXCEPTION THROWN (#%d) ####\n", ++throw_count);
        backtrace_symbols_fd(array, size, 2); // 2 == stderr
    }
    
    orig_cxa_throw(thrown_exception, pvtinfo, dest);
}

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}
 
int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
     z = division(x, y);
     cout << z << endl;
   }catch (const char* msg) {
     cerr << msg << endl;
   }
 
   return 0;
}

编译、调试

$ g++ -g exception.cc -ldl -o exception
$ gdb ./exception

Reading symbols from ./exception...
(gdb) b __cxa_throw
Breakpoint 1 at 0x132e: file exception.cc, line 17.
(gdb) r
Starting program: /mnt/e/doc/knowledge-git/bin/program/exception

Breakpoint 1, __cxa_throw (thrown_exception=0x770000007c, pvtinfo=0x0, dest=0x0) at exception.cc:17
17      void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *)) {
(gdb) bt
#0  __cxa_throw (thrown_exception=0x770000007c, pvtinfo=0x0, dest=0x0) at exception.cc:17
#1  0x000055555555544e in division (a=50, b=0) at exception.cc:39
#2  0x000055555555549c in main () at exception.cc:51
(gdb) c
Continuing.
 ################ DETECT A THROWN !!!!! #############
#### EXCEPTION THROWN (#1) ####
/mnt/e/doc/knowledge-git/bin/program/exception(__cxa_throw+0x5b)[0x555555555389]
/mnt/e/doc/knowledge-git/bin/program/exception(+0x144e)[0x55555555544e]
/mnt/e/doc/knowledge-git/bin/program/exception(+0x149c)[0x55555555549c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7ffff7bec0b3]
/mnt/e/doc/knowledge-git/bin/program/exception(+0x124e)[0x55555555524e]

Breakpoint 1, 0x00007ffff7e7c750 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) c
Continuing.
Division by zero condition!
[Inferior 1 (process 177) exited normally]

资料

C++ ABI for Itanium: Exception Handling

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表