Linux 打印堆栈方法

本文介绍了在Linux环境下,如何分别打印内核层和应用层的调用堆栈信息。通过backtrace系列函数,可以获取并转化栈信息,用于分析程序执行路径。在应用层,需要注意编译时添加-rdynamic选项,以完整显示动态链接的符号信息。
linux内核堆栈打印方法
dump_stack()

__backtrace()
linux应用层堆栈打印方法
int backtrace(void **buffer, int size);

获取当前的调用栈信息,结果存储在buffer中,返回值为栈的深度,参数size限制栈的最大深度,即最大取size步的栈信息。

char **backtrace_symbols(void *const *buffer, int size);

把backtrace获取的栈信息转化为字符串,以字符指针数组的形式返回,参数size限定转换的深度,一般用backtrace调用的返回值。

void backtrace_symbols_fd(void *const *buffer, int size, int fd);

它的功能和backtrace_symbols差不多,只不过它不把转换结果返回给调用方,而是写入fd指定的文件描述符。

示例:

void myfunc3(void)
{
   int j, nptrs;
   #define SIZE 100
   void *buffer[SIZE];
   char **strings;
   nptrs = backtrace(buffer, SIZE);
   printf("backtrace() returned %d addresses\n", nptrs);
   /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
    *  would produce similar output to the following: */
   strings = backtrace_symbols(buffer, nptrs);
   if (strings == NULL) {
       perror("backtrace_symbols");
       exit(EXIT_FAILURE);
   }
   for (j = 0; j < nptrs; j++)
       printf("%s\n", strings[j]);
   free(strings);
}

static void  /* "static" means don't export the symbol... */
myfunc2(void)
{
   myfunc3();
}

void myfunc(int ncalls)
{
   if (ncalls > 1)
       myfunc(ncalls - 1);
   else
       myfunc2();
}

int main(int argc,char *argv[])
{
   if (argc != 2) {
       fprintf(stderr,"%s num-calls\n", argv[0]);
       exit(EXIT_FAILURE);
   }
   myfunc(atoi(argv[1]));
   exit(EXIT_SUCCESS);
}

编译:

:cc prog.c -o prog

结果:

:./prog 0
backtrace() returned 6 addresses
./prog() [0x80485a3]
./prog() [0x8048630]
./prog() [0x8048653]
./prog() [0x80486a7]

没输出什么。

加上 -rdynamic:

-rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of “dlopen” or to allow obtaining backtraces from within a program.

重新编译:

cc -rdynamic  prog.c -o prog

结果:

./prog 0

backtrace() returned 6 addresses
./prog(myfunc3+0x1f) [0x8048763]
./prog() [0x80487f0]
./prog(myfunc+0x21) [0x8048813]
./prog(main+0x52) [0x8048867]
/lib/libc.so.6(__libc_start_main+0xe6) [0xaf9cc6]
./prog() [0x80486b1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值