从程序内部调用gdb打印堆栈跟踪的最佳方式是什么? [英] Best way to invoke gdb from inside program to print its stacktrace?

查看:177
本文介绍了从程序内部调用gdb打印堆栈跟踪的最佳方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用这样的函数:

  #include< stdio.h> 
#include< stdlib.h>
#include< sys / wait.h>
#include< unistd.h>

void print_trace(){
char pid_buf [30];
sprintf(pid_buf,--pid =%d,getpid());
char name_buf [512];
name_buf [readlink(/ proc / self / exe,name_buf,511)] = 0;
int child_pid = fork();
if(!child_pid){
dup2(2,1); //将输出重定向到stderr
fprintf(stdout,%s pid =%s\\\
的堆栈跟踪,name_buf,pid_buf);
execlp(gdb,gdb,--batch,-n,-ex,thread,-ex,bt,name_buf,pid_buf,NULL);
abort(); / *如果gdb无法启动* /
} else {
waitpid(child_pid,NULL,0);
}
}

我在输出中看到print_trace的细节。 / p>

有什么其他方法可以做到这一点?

解决方案

我的另一个答案(现在删除),你也希望看到行号。我不确定如何从应用程序中调用gdb。



但我将与您分享几种打印简单堆栈跟踪的方法使用函数名称和它们各自的行号而不使用gdb 。他们大多数来自 Linux Journal 非常漂亮的文章: / p>


  • 方法1:




第一种方法是按照
的顺序将print
分发给打印和日志消息以查明执行路径。在一个
复杂程序中,这个选项可能会变得繁琐乏味,即使
借助于某些GCC特定的
宏,它也可以被简化一些。
例如,考虑调试宏
,比如:



  #define TRACE_MSG fprintf(stderr,__FUNCTION__ \ 
()[%s:%d] here I am \\\
,\
__FILE__,__LINE__)




您可以通过剪切和
粘贴将整个宏快速传播
它。如果您不再需要
,只需将
定义为no-op就可以将其关闭。





  • 方法2:(它没有提及任何关于行号的信息,但是我在方法4上做了)



    但是,获得堆栈回溯的更好方法是使用
    提供的某些
    特定支持函数b glibc。关键之一是backtrace(),
    将堆栈帧从
    导入到程序的
    开头,并提供一个
    返回地址数组。然后,您可以通过

    的每个地址映射到代码中
    特定函数的主体,使用
    nm命令查看目标文件。或者,您可以使用
    更简单的方式 - 使用backtrace_symbols()。
    该函数将由
    backtrace()返回的
    返回地址列表转换为字符串列表
    ,其中包含函数名称
    offset函数和
    返回地址。字符串列表是从你的堆空间分配的
    (就好像
    你叫做malloc()),所以你应该
    free()它,只要你完成了
    它。


    我鼓励你阅读它,因为该页面有源代码的例子。为了将地址转换为函数名称,您必须使用 -rdynamic 选项编译您的应用程序。

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆