从信号处理程序打印堆栈跟踪

时间:2012-02-09 08:38:24

标签: c++ linux 64-bit stack-trace signals

我需要从Linux上运行的64位多线程C ++应用程序的信号处理程序中打印堆栈跟踪。虽然我找到了几个代码示例,但它们都没有编译。我的阻塞点是从ucontext_t结构获取调用者(生成信号的点)地址。我能找到的所有信息都指向EIP寄存器为ucontext.gregs [REG_EIP]或ucontext.eip。看起来它们都是x86特有的。我需要适用于Intel和AMD CPU的64位兼容代码。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:4)

有一个glibc函数回溯。手册页列出了调用的示例:

#define SIZE 100
void myfunc3(void) {
       int j, nptrs;

       void *buffer[100];
       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);
   }

有关更多背景信息,请参见手册页。

很难判断这是否确实可以保证信号处理程序能够正常工作,因为posix只列出了几个可以保证工作的重入函数。请记住:当您的进程的其余部分正好在malloc调用的中间时,可以调用信号处理程序。

我的猜测是,这通常有效,但可能会不时失败。对于调试,这可能已经足够了。

答案 1 :(得分:1)

获取堆栈跟踪的常用方法是获取本地地址 变量,然后添加一些幻数,取决于如何 编译器生成代码(可能取决于优化选项) 用来编译代码),然后从那里开始工作。一切都很系统 依赖,但如果你知道你在做什么,可行。

这是否适用于信号处理程序是另一个问题。我不 了解您描述的平台,但很多系统都安装了 信号处理程序的独立堆栈,没有链接返回 在用户可访问的内存中中断堆栈。