打印函数调用堆栈

在编写Java程序时,Exception类的printStacktrace()可以打印异常堆栈,这个小工具极大的提高了调试效率;虽然不是一个好习惯,却很实用。习惯了Java编程,很希望 C/C++里也有这样的小工具可以帮助调试程序.
经过几天查找,发现其实每个系统都提供了打印调用堆栈的函数;这些函数是系统相关,这里仅以Linux下的函数作说明.
Linux中共提供了三个函数用于打印调用堆栈:
 1 /**/ /* 
 2* 函数说明: 取得当前函数的调用堆栈 
 3* 参数: 
 4*     buffer:用于存储函数地址的数组 
 5*     size:buffer数组的长度 
 6* 返回值: 
 7*      存储到数组中的函数个数 
 8*/

 9 int  backtrace( void   ** buffer,  int  size); 
10   
11 /**/ /* 
12
13* 函数说明:将一组函数地址转换为字符串 
14* 参数:  
15*      buffer: 经由backtrace得到的函数地址 
16*      size: buffer数组的长度 
17* 返回值:  
18*       函数在系统中对应用字符串 
19*/

20 char   ** backtrace_symbols( void   * const   * buffer,  int  size); 
21   
22 /**/ /* 
23* 函数说明:将一组函数地址转换为字符串 
24* 参数:  
25*      buffer: 经由backtrace得到的函数地址 
26*      size: buffer数组的长度 
27*      fd: 输出结果文件描述符 
28*/

29 void  backtrace_symbols_fd( void   * const   * buffer,  int  size,  int  fd); 
30
31
32  示例程序:
33
34 ? 1
35 2
36 3
37 4
38 5
39 6
40 7
41 8
42 9
43 10
44 11
45 12
46 13
47 14
48 15
49 16
50 17
51 18
52 19
53 20
54 21
55 22
56 23
57 24
58 25
59 26
60 27
61 28  #include  < execinfo.h >  
62 #include  < stdio.h >  
63 #include  < stdlib.h >  
64 #include  < unistd.h >  
65   
66 void  myfunc3( void
67
68    int j, nptrs; 
69    #define SIZE 100 
70    void *buffer[100]; 
71    char **strings; 
72  
73    nptrs = backtrace(buffer, SIZE); 
74    printf("backtrace() returned %d addresses\n", nptrs); 
75  
76    backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO); 
77}
 
78   
79 void  myfunc( void
80
81    myfunc3(); 
82}
 
83   
84 int  main( int  argc,  char   * argv[]) 
85
86    myfunc(); 
87    return 0
88}
 
89
程序运行结果:
[dma@bp860-10 ~]$ g++ -rdynamic t.cpp -o t #这里的参数 -rdynamic 是必须
[dma@bp860-10 ~]$ ./t
backtrace() returned 5 addresses
./t(_Z7myfunc3v+0x1c)[0x4008c4]
./t(_Z6myfuncv+0x9)[0x4008f9]
./t(main+0x14)[0x400910]
/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3f37c1c40b]
./t(__gxx_personality_v0+0x3a)[0x40081a]
[dma@bp860-10 ~]$
虽然现在的程序可以输出函数调用的堆栈,但是函数多了一些前缀,比如:./t(_Z7myfunc3v+0x1c);这个问题可以通过c++fileter这个工具来解决:
[dma@bp860-10 ~]$ ./t | c++filt
./t(myfunc3()+0x1c)[0x4008c4]
./t(myfunc()+0x9)[0x4008f9]
./t(main+0x14)[0x400910]
/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3f37c1c40b]
./t(__gxx_personality_v0+0x3a)[0x40081a]
backtrace() returned 5 addresses

你可能感兴趣的:(打印函数调用堆栈)