利用backtrace函数打印函数调用栈

我们一般打印函数调用栈可以选择GDB的backtrace命令,简写bt命令都可以。这里有一个新的方法,那就是利用backtrace函数打印,不过还要加上backtrace_symbols()函数。

int backtrace(void **buffer, int size)

该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针列表。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小

在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址

backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace的返回值)函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址下面来看一个例子:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <execinfo.h>
using namespace std;

string st; 

void fun1_a(int a); 
void fun2_b(char b); 
int  fun3_c(double c); 
void fun4_d(int a); 

void fun1_a(int a)
{
    fun2_b(1.1);
}

void fun2_b(char b)
{
    fun3_c(1.1);
}

int fun3_c(double c)
{
    const int len = 200;
    void* buffer[len];
    int nptr = ::backtrace(buffer, len);
    char **strings = ::backtrace_symbols(buffer, nptr);
    if(strings){
        for(int i=0; i<nptr; ++i){
 st.append(strings[i]);
            st.push_back('\n');
        }
        free(strings);
    }
    fun4_d(4);
    return 0;
}

void fun4_d(int a)
{
    cout<<st;
}

int main()
{
    fun1_a(1);
    return 0;
}

输出如下:


直接运行的话输出是这样的,我们看不出调用了什么函数,下面加上一个选项。



选项 -rdynamic 用来通知链接器将所有符号添加到动态符号表中。_Z6是所有函数返回值,其中fun3_c是int类型,也是_Z6,这不就是我们说的返回值类型不能决定函数重载吗?fun3_c函数名,d是double类型,其他函数和fun3_c都一样。


如果我们想知道函数在第几行,可以这样:


OK。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值