当前位置:   article > 正文

linux c/c++抓取分析崩溃日志_linux c++ 程序崩溃打印堆栈

linux c++ 程序崩溃打印堆栈

前言

本文章旨在作为笔记,温故而知新,也希望能帮到各位有需要的道友,若有任何建议或探讨可加 QQ群进行交流:887939177

目的

在linux实际项目中(即程序已上线),会遇到程序无缘无故崩溃的现象,此时常规日志可能无法分析出故障原因。
本文介绍两种方式,方式一为系统生成core文件模式,方式二程序监听崩溃信号并打印堆栈信息。

推荐使用方式二,(方式一会根据程序内存使用大小会影响core文件大小,若程序内存开销很大会造成core文件很大,在写文件时会影响系统性能)

方式一:系统生成core文件模式

1.首先输入命令: ulimit -c,如果返回0,说明当前没有开启自动保存崩溃文件功能,可通过以下命令开启并设置文件大小限制(unlimited代表不限制,若需限制可写具体数值)。

ulimit -c unlimited

    2.设置崩溃文件保存路径(需保证文件夹存在),命令如下,

    echo "/var/core/core-%e-%p-%t-%s.err" > /proc/sys/kernel/core_pattern

      至此配置完成,当程序崩溃时系统自动将信息写入指定的文件夹并按规则命名。

      3.打印崩溃日志,命令如下,

      gdb -c /var/core/[生成的core文件名] [可执行文件]
      gdb -c /var/core/core-test-18829-1549201876-11.err ./test
      • 1

      执行上述命令后,会进入gdb调试模式,然后输入命令:bt,便会打印崩溃堆栈。

      方式二:程序监听崩溃信号并打印堆栈信息

      1.在程序中添加进程信号监听,例如:

      signal(SIGSEGV, sigHandler);
      signal(SIGABRT, sigHandler);
      • 1

      2.实现绑定函数sigHandler,如下:

      void sigHandler(int signo) 
      {
      	LOG_ERROR_ARGS("=====recv SIGINT %d=====", signo);
      	
      	//打印错误堆栈信息
      	LOG_ERROR("----------------------------Dump Program Error Strings-------------------------");
      	int j = 0, nptrs = 0;
       	void* buffer[100] = { NULL };
       	char** strings = NULL;
       	nptrs = backtrace(buffer, 100);
       	LOG_ERROR_ARGS("backtrace() returned %d addresses", nptrs);
       	strings = backtrace_symbols(buffer, nptrs);
       	if (strings == NULL) {
        		LOG_ERROR("backtrace_symbols null");
        		LOG_ERROR("-------------------------------------------------------------------------------");
        		return;
       	}
       	for (j = 0; j < nptrs; j++) {
        		LOG_ERROR_ARGS("  [%02d] %s", j, strings[j]);
       	}
       	free(strings);
      	LOG_ERROR("-------------------------------------------------------------------------------");
      	
      	//恢复默认信号操作
      	signal(signo, SIG_DFL);
        	raise(signo);
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

      以上主要利用backtrace及backtrace_symbols来获取程序崩溃时的堆栈信息,后续就是以此信息来查找程序具体执行到哪一步崩溃的。

      3.编译程序时请添加 -g -rdynamic 的编译选项,

      gcc -g -rdynamic -o test test.c

        3.打印信息大致如下:

        2020-07-15 16:54:34.669 [ERROR] 140084499824832 : =====recv SIGINT 11=====
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 : RsuGasStation.cpp[14] ----------------------------Dump Program Error Strings-------------------------
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 : backtrace() returned 6 addresses
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [00] ./rsu_gasstation(_Z23DumpProgramErrorStringsv+0x131) [0x559abf9059b7]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [01] ./rsu_gasstation(_Z10sigHandleri+0x113) [0x559abf905e95]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [02] /lib/x86_64-linux-gnu/libc.so.6(+0x3efd0) [0x7f67f5181fd0]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [03] ./rsu_gasstation(main+0x17d) [0x559abf906062]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [04] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0x7f67f5164b97]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [05] ./rsu_gasstation(_start+0x2a) [0x559abf8f9d1a]
        2020-07-15 16:54:34.669 [ERROR] 140084499824832 : RsuGasStation.cpp[32] -------------------------------------------------------------------------------
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10

        4.利用nm命令生成函数映射地址列表文件,命令如下:

        nm -n [可执行文件] [生成的函数列表文件名]
        nm -n test test.nm
        • 1

        5.在函数映射地址列表文件中查找错误信息中的对应函数,比如此行的main函数,

        2020-07-15 16:54:34.669 [ERROR] 140084499824832 :   [03] ./rsu_gasstation(main+0x17d) [0x559abf906062]
        
        • 1

        在文件中查找到的信息为:

        0000000000027ee5 T main
        
        • 1

        6.此时可利用错误打印信息中的(main+0x17d),以及文件查找出来的地址,使用addr2line命令获取相关信息,如下:

        addr2line -e [可执行文件] [地址:0x27ee5 + 0x17d]
        addr2line -e test 0x28062
        • 1

        至此你便可看到具体信息,信息大致如下,可直观看到哪个函数哪一行,

        sl@sl_rsu:~/projects/RsuGasStation/bin/x64/Debug$ addr2line -e rsu_gasstation 0x28062
        /home/sl/projects/RsuGasStation/RsuGasStation.cpp:87 (discriminator 17)
        sl@sl_rsu:~/projects/RsuGasStation/bin/x64/Debug$ 
        
        • 1
        • 2
        • 3

        signal信号参考网址:https://www.cnblogs.com/frisk/p/11602973.html
        文章描述比较简单,希望能帮助到朋友们,如有疑问或建议,欢迎加QQ群(887939177)进行讨论!
        QQ群二维码

        声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/245772
        推荐阅读
        相关标签
          

        闽ICP备14008679号