c - 如何获得更详细的回溯

标签 c linux

<分区>

我正在尝试在我的 C++ 程序终止时打印回溯。函数打印回溯如下;

   void print_backtrace(void){

       void *tracePtrs[10];
       size_t count;

       count = backtrace(tracePtrs, 10);

       char** funcNames = backtrace_symbols(tracePtrs, count);

       for (int i = 0; i < count; i++)
           syslog(LOG_INFO,"%s\n", funcNames[i]);

       free(funcNames);

}

它给出了这样的输出;

   desktop program: Received SIGSEGV signal, last error is : Success
   desktop program: ./program() [0x422225]
   desktop program: ./program() [0x422371]
   desktop program: /lib/libc.so.6(+0x33af0) [0x7f0710f75af0]
   desktop program: /lib/libc.so.6(+0x12a08e) [0x7f071106c08e]
   desktop program: ./program() [0x428895]
   desktop program: /lib/libc.so.6(__libc_start_main+0xfd) [0x7f0710f60c4d]
   desktop program: ./program() [0x4082c9]

有没有办法通过函数名称和行获得更详细的回溯,例如 gdb 输出?

最佳答案

是 - 将 -rdynamic 标志传递给链接器。这将导致链接器将代码中所有非静态函数的名称放入链接表中,而不仅仅是导出的函数。

您付出的代价是您的程序启动时间稍长一些。对于中小型程序,您不会注意到它。您得到的是 backtrace() 能够为您提供回溯中所有非静态函数的名称。

但是 - 请注意:您需要注意几个问题:

  1. backtrace_symbols 从 malloc 分配内存。如果您由于 malloc arena 损坏(很常见)而进入 SIGSEGV,您将在此处出现双重错误并且永远看不到您的回溯。

  2. 根据此运行的平台(例如 x86),您崩溃的确切函数的地址/函数名称将在堆栈上替换为信号处理程序的返回地址。您需要从这些平台的信号处理程序参数中获取崩溃函数的正确 EIP。

  3. syslog 不是异步信号安全功能。它可能会在内部获取一个锁,如果在崩溃发生时获取了该锁(因为您在另一次调用 syslog 的过程中崩溃了),那么您就有了一个死锁

如果您想了解所有血淋淋的细节,请观看我在 OLS 上的演讲视频:http://free-electrons.com/pub/video/2008/ols/ols2008-gilad-ben-yossef-fault-handlers.ogg

关于c - 如何获得更详细的回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5945775/

相关文章:

linux - 如何打印特定用户名的 CMD1、PID、PPID、USER、UID、GID,它应该采用相同的格式,我已经使用了这个命令,但它向所有用户显示

linux - 重命名每个组中的最新文件

c - 输出没有立即出现

c - 以下 C 程序的输出是什么

c - 使用 gcc,如何将库 (-lpthread) 包含到我自己的静态用户库中?

c - 尝试使用 c 反转字符串

linux - 将输入重定向到后台运行的脚本

c - 分配语句的结果后跟表达式和分号

python - 带有自动启动的 OpenCV 的 Raspberry Pi (Linux) 上的应用程序

Linux - 如何列出所有用户及其 UID