当我的程序崩溃时如何自动生成堆栈跟踪

新手上路,请多包涵

我正在使用 GCC 编译器在 Linux 上工作。当我的 C++ 程序崩溃时,我希望它自动生成堆栈跟踪。

我的程序由许多不同的用户运行,它也可以在 Linux、Windows 和 Macintosh 上运行(所有版本都使用 gcc 编译)。

我希望我的程序能够在崩溃时生成堆栈跟踪,并且下次用户运行它时,它会询问他们是否可以将堆栈跟踪发送给我,以便我可以追踪问题。我可以处理向我发送信息,但我不知道如何生成跟踪字符串。有任何想法吗?

原文由 KPexEA 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
2 个回答

对于 Linux,我相信 Mac OS X,如果你使用 gcc,或者任何使用 glibc 的编译器,你可以使用 execinfo.h 中的 backtrace() 函数来打印堆栈跟踪并在你得到一个优雅退出分段故障。文档可以 在 libc 手册 中找到。

这是一个示例程序,它安装 SIGSEGV 处理程序并在出现段错误时将堆栈跟踪打印到 stderr 。这里的 baz() 函数会导致触发处理程序的段错误:

 #include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

void handler(int sig) {
  void *array[10];
  size_t size;

  // get void*'s for all entries on the stack
  size = backtrace(array, 10);

  // print out all the frames to stderr
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}

void baz() {
 int *foo = (int*)-1; // make a bad pointer
  printf("%d\n", *foo);       // causes segfault
}

void bar() { baz(); }
void foo() { bar(); }

int main(int argc, char **argv) {
  signal(SIGSEGV, handler);   // install our handler
  foo(); // this will call foo, bar, and baz.  baz segfaults.
}

使用 -g -rdynamic 编译会在输出中获得符号信息,glibc 可以使用它来制作一个很好的堆栈跟踪:

 $ gcc -g -rdynamic ./test.c -o test

执行这个得到你这个输出:

 $ ./test
Error: signal 11:
./test(handler+0x19)[0x400911]
/lib64/tls/libc.so.6[0x3a9b92e380]
./test(baz+0x14)[0x400962]
./test(bar+0xe)[0x400983]
./test(foo+0xe)[0x400993]
./test(main+0x28)[0x4009bd]
/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3a9b91c4bb]
./test[0x40086a]

这显示了堆栈中每个帧来自的加载模块、偏移量和函数。 Here you can see the signal handler on top of the stack, and the libc functions before main in addition to main , foo , barbaz

原文由 Todd Gamblin 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您仍然想像我一样单独行动,您可以链接到 bfd 并避免使用 addr2line 就像我在这里所做的那样:

https://github.com/gnif/LookingGlass/blob/master/common/src/platform/linux/crash.c

这将产生输出:

 [E]        crash.linux.c:170  | crit_err_hdlr                  | ==== FATAL CRASH (a12-151-g28b12c85f4+1) ====
[E]        crash.linux.c:171  | crit_err_hdlr                  | signal 11 (Segmentation fault), address is (nil)
[E]        crash.linux.c:194  | crit_err_hdlr                  | [trace]: (0) /home/geoff/Projects/LookingGlass/client/src/main.c:936 (register_key_binds)
[E]        crash.linux.c:194  | crit_err_hdlr                  | [trace]: (1) /home/geoff/Projects/LookingGlass/client/src/main.c:1069 (run)
[E]        crash.linux.c:194  | crit_err_hdlr                  | [trace]: (2) /home/geoff/Projects/LookingGlass/client/src/main.c:1314 (main)
[E]        crash.linux.c:199  | crit_err_hdlr                  | [trace]: (3) /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xeb) [0x7f8aa65f809b]
[E]        crash.linux.c:199  | crit_err_hdlr                  | [trace]: (4) ./looking-glass-client(_start+0x2a) [0x55c70fc4aeca]

原文由 Geoffrey 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题