函数调用栈实现
#include <stdio.h>
#include <execinfo.h>
#include <malloc.h>
#include <cxxabi.h>
void printCallStack_simple()
{
int size = 16; // 最多打印16层调用栈
void *buffer[size]; // 用于存放调用栈信息
int count = backtrace(buffer, size); // 获取调用栈
char **ptr = backtrace_symbols(buffer, count); // 将调用栈信息转成字符串
for (int i = 0; i < count; i++)
{ // 打印字符串
printf("%s", ptr[i]);
}
free(ptr); // 释放分配的内存
}
void printCallStack()
{
void *buffer[100] = {NULL};
char **trace = NULL;
int size = backtrace(buffer, 100);
trace = backtrace_symbols(buffer, size);
if (NULL == trace)
{
return;
}
size_t name_size = 100;
char *name = (char *)malloc(name_size);
for (int i = 0; i < size; ++i)
{
char *begin_name = 0;
char *begin_offset = 0;
char *end_offset = 0;
for (char *p = trace[i]; *p; ++p)
{ // 利用了符号信息的格式
if (*p == '(')
{ // 左括号
begin_name = p;
}
else if (*p == '+' && begin_name)
{ // 地址偏移符号
begin_offset = p;
}
else if (*p == ')' && begin_offset)
{ // 右括号
end_offset = p;
break;
}
}
if (begin_name && begin_offset && end_offset)
{
*begin_name++ = '\0';
*begin_offset++ = '\0';
*end_offset = '\0';
int status = -4; // 0 -1 -2 -3
char *ret = abi::__cxa_demangle(begin_name, name, &name_size, &status);
if (0 == status)
{
name = ret;
printf("%s:%s+%s\n", trace[i], name, begin_offset);
}
else
{
printf("%s:%s()+%s\n", trace[i], begin_name, begin_offset);
}
}
else
{
printf("%s\n", trace[i]);
}
}
free(name);
free(trace);
printf("----------done----------\n");
}
void test3(int n) { printCallStack(); }
void test2(int n) { test3(3); }
void test1(int n) { test2(2); }
int main()
{
test1(1);
}
[root@centos7 ~]# g++ -g -rdynamic test_trace.cc
[root@centos7 ~]# ./a.out
./a.out:printCallStack2()+0x41
./a.out:test3(int)+0x10
./a.out:test2(int)+0x15
./a.out:test1(int)+0x15
./a.out:main()+0xe
/lib64/libc.so.6:__libc_start_main()+0xf5
./a.out() [0x400969]
----------done----------