在Linux中打印函数调用栈

Linux下打印函数调用栈的方法
本文介绍了在Linux中如何使用backtrace、backtrace_symbols和backtrace_symbols_fd三个函数来打印函数调用栈,这对于理解和调试代码的执行流程非常有帮助。通过示例代码展示了如何封装这些函数以方便在需要时输出调用栈信息。

在实际调试程序时,往往需要知道函数的调用关系,尤其是在阅读一些开源代码或者linux kernel程序时,打印出函数的调用栈有助于我们从整体上把握代码框架结构。linux提供了三个函数帮助我们打印函数调用栈。

/*
* 函数说明: 取得当前函数的调用堆栈
* 参数:
*     buffer:用于存储函数地址的数组
*     size:buffer数组的长度
* 返回值:
*      存储到数组中的函数个数
*/
int backtrace(void **buffer, int size);
 
/*
*
* 函数说明:将一组函数地址转换为字符串
* 参数:
*      buffer: 经由backtrace得到的函数地址
*      size: buffer数组的长度
* 返回值:
*       函数在系统中对应用字符串
*/
char **backtrace_symbols(void *const *buffer, int size);
 
/*
* 函数说明:将一组函数地址转换为字符串
* 参数:
*      buffer: 经由backtrace得到的函数地址
*      size: buffer数组的长度
*      fd: 输出结果文件描述符
*/
void backtrace_symbols_fd(void *const *buffer, int size, int fd);

针对上面三个函数,进行了如下的封装,可以直接调用以下

Linux系统中,有多种方法可以打印函数调用栈。 ### 方法一:使用 `<execinfo.h>` 头文件中的函数 该方法可用于用户空间程序,代码示例如下: ```c #include <execinfo.h> #include <stdio.h> void print_callstack() { void *bt[30]; char **strings; size_t sz; sz = backtrace(bt, 30); strings = backtrace_symbols(bt, sz); for(int i = 0; i < sz; ++i) printf("%s\n", strings[i]); } ``` ### 方法二:使用内核函数 `dump_stack()` 在Linux内核代码中,可以使用 `dump_stack()` 函数将栈内容和回溯信息打印到内核日志中。使用时需要包含 `<linux/kernel.h>` 头文件,示例如下: ```c #include <linux/kernel.h> void some_kernel_function() { // ... dump_stack(); // ... } ``` ### 方法三:自定义打印函数调用栈函数 下面是一个更完整的用户空间程序示例,展示了如何自定义一个打印函数调用栈的函数: ```c #include <stdio.h> #include <execinfo.h> #define MAX_DEPTH 20 void PrintfStackFunName(void) { void *buff[MAX_DEPTH] = { 0 }; unsigned int depth = backtrace(buff, MAX_DEPTH); char **funName = backtrace_symbols(buff, depth); for (int i = 0; i < MAX_DEPTH; i++) { if (i >= depth) { break; } printf("i = %d, func = %s\n", i, funName[i]); } } void func4(void) { printf("%s [line] = %d\n", __FUNCTION__, __LINE__); PrintfStackFunName(); } void func3(void) { printf("%s [line] = %d\n", __FUNCTION__, __LINE__); func4(); } void func2(void) { printf("%s [line] = %d\n", __FUNCTION__, __LINE__); func3(); } void func1(void) { printf("%s [line] = %d\n", __FUNCTION__, __LINE__); func2(); } int main(void) { func1(); return 0; } ``` 将上述代码保存为一个 `.c` 文件,编译并运行,就可以看到函数调用栈的输出。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值