• C++后台服务崩溃堆栈日志


    C++后台服务崩溃堆栈日志

      C/C++后台服务运行过程中总会出现一些不容易重现的崩溃故障,由于重现频率低,同时运行在服务器上,导致无法调试,此外服务直接崩溃,常规日志无法截获到有用信息,这时如果能够保留服务崩溃现场,将对后期的Bug调试起到事半功倍的效果。打印出崩溃时刻服务的堆栈信息的需求应运而生。

    前提条件

      编译程序服务的Debug版本,没有调试信息,神仙也没有办法。-rdynamic 为可选参数(会在打印的堆栈信息中增加调用函数名称)。

      gcc: gcc -g -rdynamic main.cpp

      cmake: set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -rdynamic -O0 -Wall -g")

    运行结果:

    trigger signal: 11
    ./test_cario(_Z14signal_handleri+0x5e) [0x400e4b]
    /lib64/libc.so.6(+0x35270) [0x7fc0c1e59270]
    ./test_cario(_Z4add2PKc+0x1f) [0x400f04]
    ./test_cario(_Z3addPKc+0x18) [0x400f61]
    ./test_cario(main+0xbc) [0x40101f]
    /lib64/libc.so.6(__libc_start_main+0xf5) [0x7fc0c1e45c05]
    ./test_cario() [0x400d29]

      上面信息显示了崩溃时的调用堆栈,输出的信息只打印了调用地址,还需要对这些地址进行可视化:

    [root@localhost debug]$ addr2line -e a.out 0x400e4b
    /home/root/test/main.cpp:13
    [root@localhost debug]$ addr2line -e a.out 0x400f04
    /home/root/test/main.cpp:30
    [root@localhost debug]$ addr2line -e a.out 0x400f61
    /home/root/test/main.cpp:36
    [root@localhost debug]$ addr2line -e a.out 0x40101f
    /home/root/test/main.cpp:56

    示例程序

    #include <iostream>
    #include <zconf.h>
    #include <signal.h>
    #include <execinfo.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void signal_handler( int s ) {
        fprintf( stderr, "trigger signal: %d
    ", s );
    
        void* pszstack[256] = {NULL};
        int stacknum = backtrace( pszstack, 256 );
        if ( stacknum > 0 ) {
            char** stacktrace = backtrace_symbols( pszstack, stacknum );
            for ( int i = 0; i < stacknum; ++i ) {
                fprintf( stderr, "%s
    ", stacktrace[i] );
            }
            free( stacktrace );
        } else {
           fprintf( stderr, "no stack trace: %d", stacknum );
        }
        exit(0);
    }
    
    void add2( const char* psz )
    {
        int a = 0;
        int b = 1;
        std::cout << a+b << "data: " << psz[0] << std::endl;
    }
    
    void add( const char* psz )
    {
        add2( psz );
    }
    
    int main() {
    
        signal( SIGPIPE, SIG_IGN );
        signal( SIGSEGV, signal_handler );
        signal( SIGABRT, signal_handler );
        signal( SIGFPE, signal_handler );
        signal( SIGSYS, signal_handler );
        signal( SIGIO, signal_handler );
    
        char* psztemp = NULL;
        for ( int i = 0; i < 5; ++i )
        {
            std::cout << "sleep: " << i << std::endl;
            sleep( 1 );
        }
    
        add(psztemp);
    
        for ( int i = 0; i < 5; ++i )
        {
            std::cout << "sleep2: " << i << std::endl;
            sleep( 1 );
        }
        
        return 0;
    }
    
  • 相关阅读:
    Mybatis result相关查询标签使用细则
    9.4 代码缓存 Java性能优化节选
    JarScan
    碎片 Java性能优化节选
    小方法的好处 Java性能优化p203
    HotSpot JIT基础
    JITWatch
    新手电吉他是三单还是单单双?
    JIT编译日志
    修改Oracle数据库的字符集(UTF8→ZHS16GBK)
  • 原文地址:https://www.cnblogs.com/wanghaiyang1930/p/8884848.html
Copyright © 2020-2023  润新知