胖鸭 2008-09-16 20:58
浏览 914
已采纳

如何在程序崩溃时自动生成堆栈跟踪

I am working on Linux with the GCC compiler. 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?

转载于:https://stackoverflow.com/questions/77005/how-to-automatically-generate-a-stacktrace-when-my-program-crashes

  • 写回答

27条回答 默认 最新

  • 笑故挽风 2008-09-16 21:30
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(26条)

报告相同问题?

悬赏问题

  • ¥15 高价求中通快递查询接口
  • ¥15 解决一个加好友限制问题 或者有好的方案
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?