本文介绍了如何在我的gcc C ++程序崩溃时自动生成堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的程序由许多不同的用户运行,它也可以在Linux,Windows上运行。

当我的C ++程序崩溃时,我希望它自动生成堆栈跟踪。和Macintosh(所有版本都使用 gcc 编译)。



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

解决方案

对于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处理程序(int sig){
void * array [10];
size_t size;

//获取堆栈中所有条目的void *'s
size = backtrace(array,10);

//将所有帧打印到stderr
fprintf(stderr,Error:signal%d:\\\
,sig);
backtrace_symbols_fd(数组,大小,STDERR_FILENO);
exit(1);


void baz(){
int * foo =(int *) - 1; //制作一个糟糕的指针
printf(%d\\\
,* foo); //导致段错误
}

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


int main(int argc,char ** argv){
signal(SIGSEGV,handler); //安装我们的处理程序
foo(); //这会叫foo,bar和baz。巴斯段错误。
}

编译-g -rdynamic 在你的输出中获得符号信息,glibc可以使用它来创建一个不错的堆栈跟踪:

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

执行此操作可获得此输出:

  $ ./test 
错误:信号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 之外的 main 之前的libc函数, foo bar baz


When my C++ program crashes I would like it to automatically generate a stacktrace.

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?

解决方案

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.

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:\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.
}

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]

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.

这篇关于如何在我的gcc C ++程序崩溃时自动生成堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 03:02