一、打印堆栈可以方便问题定位,找到具体的函数调用流程。
二、打印堆栈的方法
2.1、用户态
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <execinfo.h>
#define DUMP_DEPTH 20
void dump(void)
{
int i = 0;
size_t size = 0;
char **strings = NULL;
void *buffer[DUMP_DEPTH] = {0};
size = backtrace(buffer, DUMP_DEPTH);
printf("get %zd stack frames\n", size);
strings = backtrace_symbols(buffer, size);
if (strings == NULL)
{
printf("backtrace_symbols error.");
exit(-1);
}
for (i = 0; i < size; i++)
{
printf("%s\n", strings[i]);
}
free(strings);
strings = NULL;
exit(0);
}
void func_c()
{
dump();
}
void func_b()
{
func_c();
}
void func_a()
{
func_b();
}
int main(int argc, const char *argv[])
{
func_a();
return 0;
}
运行结果
看不到具体的函数名调用关系,不用紧,可以使用addr2line解析出函数名,具体参考
https://blog.csdn.net/sydyh43/article/details/119487171 的4.2部分
PS:应用层coredump实现方式,创建SIGSEGV信号对应信号处理函数为dump,如:
signal(SIGSEGV, dump)
2.2、内核态
#include <linux/stacktrace.h>
#define BKTRACE_DEPTH 20
void print_stack(void)
{
unsigned long backtrace[BKTRACE_DEPTH];
struct stack_trace trace;
memset(&trace, 0, sizeof(trace));
memset(backtrace, 0, BKTRACE_DEPTH * sizeof(unsigned long));
trace.max_entries = BKTRACE_DEPTH;
trace.entries = backtrace;
// save_stack_trace_tsk(ptask, &trace); //指定task = pstak
save_stack_trace(&trace); //默认的task是current
print_stack_trace(&trace, 0);
}
上面的实现方式堆栈深度可以按自己需求设置,其中默认堆栈深度,使用方法更方便。直接在需要的函数内插入下面的代码
dump_stack();