c/c++ backtrace打印函数调用栈

文章介绍了如何在C/C++程序中使用backtrace()和backtrace_symbols()获取原始栈信息,然后通过addr2line工具解析成文件+行号+函数名的形式。此外,作者还提供了一个自动化解析工具,简化了手动解析的过程,并展示了如何在代码中集成调试功能,如在遇到指针错误时打印调用栈。

1 打印原始栈信息

核心函数 :backtrace() 和 backtrace_symbols()
头文件:#include <execinfo.h>
例子:

    void *array[32] = {
   
   0};
	size_t size;
	char **strings;
	
	size = backtrace (array, 32);
	strings = backtrace_symbols (array, size);
	for (int i = 1; i < size -2; i++)
	{
   
   
		printf("%s ",strings[i]);
	}

2 原栈信息的解析 => 文件+行号+函数名

核心命令:addr2line
其实很简单,先得到原栈信息,然后
addr2line -Cif -e [可执行文件或者.so文件名] [地址,如果是.so文件要计算相对地址]
比如这样:addr2line -Cif -e ./a 0x400d27

下面是一个例子,我开了.h里面的调试开关的.
在这里插入图片描述
先看最下面的,对 ./m(main+0x107) [0x400d27]的解析就是直接用的命令addr2line -Cif -e ./m 0x400d27

然后看动态库的解析,./libtest.so(_Z7fun_funv+0x9) [0x7f85cf46a615] => addr2line -Cif -e ./libtest.so 0x615
0x615 = 0x7f85cf46a615 - 0x7f85cf46a000,0x7f85cf46a000是怎么知道的?
用/proc/self_pid/maps命令得到,图片里面上面部分的打印都是这个命令的输出.带 r-xp项的.

3 工具

如果每次都手动解析,那也太麻烦了.所以我写了一个自动解析工具(代码在后面).
怎么使用:step1:#include"debug.h" step2: debug_backtrace_init();
例子:
main.c

#include<stdio.h>
#include"debug.h"  //step1

/*操作空指针*/
int test_null_ptr()
{
   
   
    int *p = NULL;
    *p = 1;
    return 0;
}

int to_do()
{
   
   
    int a = 100;
    a++;
    test_null_ptr();
    return a;
}

int main()
{
   
   
    char c[10];
    debug_backtrace_init();//step2
    to_do();
    gets(c);
    return 0;
}
编译运行:要加 -g
gcc main.c debug.c -g -o a
./a

结果:
[dump_library_maps][159]debug_backtrace_init success,num_exe:7

##################backtrace###################
./a() [0x40145b] signal_exit() /workbench/jlh/1/debug.c:242
/lib/x86_64-linux-gnu/libc.so.6(+0x360b0) [0x7f2445d130b0] ??() ??:0
./a() [0x400a74] test_null_ptr() /workbench/jlh/1/main.c:8
./a() [0x400a9e] to_do() /workbench/jlh/1/main.c:17
./a() [0x400ace] main() /workbench/jlh/1/main.c:25
################################################
Error: signal_str:SIGSEGV(11)

4 代码

debug.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <execinfo.h>
#include <signal.h>
#include "debug.h"

/*内部结构体*/
typedef struct {
   
   
   char not_care
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值