linux 下C/C++程序常用调试方法(gdb)
void dump(int __signal) { const int __max_stack_flow = 20; void* __array[__max_stack_flow]; char** __strings; size_t __size = backtrace(__array,__max_stack_flow); printf("backtrace() returned %d addresses\n", (int)__size); __strings = backtrace_symbols(__array,__size); if(NULL == __strings) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } fprintf (stderr,"obtained %zd stack frames.nm", __size); for (size_t __i = 0; __i < __size; ++__i) { printf("%s\n", __strings[__i]); } // This __strings is malloc(3)ed by backtrace_symbols(), and must be freed here free (__strings); exit(0); }
void segv_fun() { unsigned char* __ptr = 0x00; *__ptr = 0x00; } void register_signal(int __signal) { signal(__signal, dump); } void TestDump::test_signal_segv() { printf("TestDump::test_signal SIGSEGV\n"); register_signal(SIGSEGV); segv_fun(); }
运行输出:
从运行结果可以看到,程序SIGSEGV中断触发了dump函数,dump打印出了6帧,第一帧:/easy_main(_Z4dumpi+0x26) [0x402896] 是在执行dump;第二帧:/lib64/libc.so.6() [0x332ae329a0] 是调用libc的库函数;第三帧:./easy_main(_ZN8TestDump5myRunEPKcb+0x5f) [0x402d2f],这个看起来有点奇怪,这一串貌似可以看出来一些信息,TestDump?不能很快定位。不用急,如果出现这个请看看,我们可以借助addr2line,通过地址转换到对应文件的行数。
再看看源代码文件,void segv_fun() { unsigned char* __ptr = 0x00; *__ptr = 0x00; }
这下就知道问题所在之处了吧!第N帧......
void dump_for_gdb(int __signal) { const int __max_buf_size = 512; char __buf[__max_buf_size] = {}; char __cmd[__max_buf_size] = {}; FILE* __file; snprintf(__buf, sizeof(__buf), "/proc/%d/cmdline", getpid()); if(!(__file = fopen(__buf, "r"))) { exit(0); } fclose(__file); if(__buf[strlen(__buf) - 1] == '\n') // warning: multi-character character constant [-Wmultichar] { __buf[strlen(__buf) - 1] = '\0'; // warning: multi-character character constant [-Wmultichar] } snprintf(__cmd, sizeof(__cmd), "gdb %s %d",__buf, getpid()); system(__cmd); exit(0); }
void register_signal_for_gdb(int __signal) { signal(__signal, dump_for_gdb); }
void TestDump::test_dump_for_gdb() { printf("TestDump::test_dump_for_gdb SIGSEGV\n"); register_signal_for_gdb(SIGSEGV); segv_fun2(); }
输出结果
当然,我们可以把这些东西整合起来,比如在项目最终上线后,我们希望这个操作更加简单,因为到了运营阶段,操作者可能不是开发者,而是运维人员,我们希望用更简单,直接的方式,把这些信息提取出来,那就需要更进一步的工作了。我们之前采用的方法是:把dump的堆栈信息写的文件中,然后使用shell读取这些堆栈信息,病使用addr2line转化到具体的文件行数或者函数并保存最终文件。这样运维人员只需要把最终的文件给开发人员,便可分析定位问题了。目前所常用的就这些了,如果有更好的方式,欢迎补充。
引用代码:
Linux 信号signal处理机制
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。