问题描述
我正在使用 GCC 编译器在 Linux 上工作.当我的 C++ 程序崩溃时,我希望它自动生成堆栈跟踪.
I am working on Linux with the GCC compiler. When my C++ program crashes I would like it to automatically generate a stacktrace.
我的程序由许多不同的用户运行,它也可以在 Linux、Windows 和 Macintosh 上运行(所有版本都使用 gcc
编译).
My program is being run by many different users and it also runs on Linux, Windows and Macintosh (all versions are compiled using gcc
).
我希望我的程序能够在崩溃时生成堆栈跟踪,下次用户运行它时,它会询问他们是否可以将堆栈跟踪发送给我,以便我可以追踪问题.我可以处理向我发送信息,但我不知道如何生成跟踪字符串.有什么想法吗?
I would like my program to be able to generate a stack trace when it crashes and the next time the user runs it, it will ask them if it is ok to send the stack trace to me so I can track down the problem. I can handle the sending the info to me but I don't know how to generate the trace string. Any ideas?
推荐答案
对于 Linux 和 Mac OS X,如果你使用 gcc,或者任何使用 glibc 的编译器,你可以使用 execinfo.h
打印堆栈跟踪并在遇到分段错误时正常退出.文档可以在在 libc 手册中找到.
For Linux and I believe Mac OS X, if you're using gcc, or any compiler that uses glibc, you can use the backtrace() functions in execinfo.h
to print a stacktrace and exit gracefully when you get a segmentation fault. Documentation can be found in the libc manual.
这是一个示例程序,它安装 SIGSEGV
处理程序并在出现段错误时将堆栈跟踪打印到 stderr
.此处的 baz()
函数会导致触发处理程序的段错误:
Here's an example program that installs a SIGSEGV
handler and prints a stacktrace to stderr
when it segfaults. The baz()
function here causes the segfault that triggers the handler:
#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:
", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
void baz() {
int *foo = (int*)-1; // make a bad pointer
printf("%d
", *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 可以使用这些信息来制作漂亮的堆栈跟踪:
Compiling with -g -rdynamic
gets you symbol info in your output, which glibc can use to make a nice stacktrace:
$ gcc -g -rdynamic ./test.c -o test
执行这个会得到这个输出:
Executing this gets you this output:
$ ./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]
这显示了堆栈中每个帧来自的加载模块、偏移量和函数.在这里你可以看到堆栈顶部的信号处理程序,以及 main
之前的 libc 函数以及 main
、foo
、bar
和 baz
.
This shows the load module, offset, and function that each frame in the stack came from. Here you can see the signal handler on top of the stack, and the libc functions before main
in addition to main
, foo
, bar
, and baz
.
这篇关于当我的程序崩溃时如何自动生成堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!