zoukankan      html  css  js  c++  java
  • linux应用程序调试----backtrace

    打印堆栈是调试的常用方法,一般在系统异常时,我们可以将异常情况下的堆栈打印出来,这样十分方便错误查找。

    先介绍下比较简单的backtrace方式,后面有机会可以尝试下core文件+gdb的方式。

    backtrace打印堆栈方式

    编译选项增加  -O0 -rdynamic -g -funwind-tables -ffunction-sections

    CFLAGS ?= -mcpu=ck810 -static -mlittle-endian -Werror -O0 -rdynamic -g -funwind-tables -ffunction-sections

    ASFLAGS += -O0

    代码添加

    #include <signal.h>       /* for signal */  
    #include <execinfo.h>     /* for backtrace() */  
    
    #define BACKTRACE_SIZE   32  
      
    void dump(void)  
    {  
        int j, nptrs;  
        void *buffer[BACKTRACE_SIZE];  
        char **strings;  
    
        printf("backtrace...
    ");
        
        nptrs = backtrace(buffer, BACKTRACE_SIZE);  
          
        printf("backtrace() returned %d addresses
    ", nptrs);  
      
        strings = backtrace_symbols(buffer, nptrs);  
        if (strings == NULL) {  
            perror("backtrace_symbols");  
            exit(EXIT_FAILURE);  
        }  
      
        for (j = 0; j < nptrs; j++)  
            printf("  [%02d] %s
    ", j, strings[j]);  
      
        free(strings);  
    }  
    
    
    
    void signal_handler(int signo)  
    {  
          
    #if 0     
        char buff[64] = {0x00};  
              
        sprintf(buff,"cat /proc/%d/maps", getpid());  
              
        system((const char*) buff);  
    #endif    
      
        printf("
    =========>>>catch signal %d <<<=========
    ", signo);  
          
        printf("Dump stack start...
    ");  
        dump();  
        printf("Dump stack end...
    ");  
    
        //exit(-1);
        signal(signo, SIG_DFL); /* 恢复信号默认处理 */  
        raise(signo);           /* 重新发送信号 */  
    
        printf("app exit
    ");  
    }  

    int main(void)
    {
      signal(SIGABRT, signal_handler);
      signal(SIGBUS, signal_handler); 
      signal(SIGSEGV, signal_handler); 
    
    }
    

      

    执行结果:

    =========>>>catch signal 11 <<<=========
    Dump stack start...
    backtrace...
    backtrace() returned 7 addresses
    [00] ./app-demo() [0xbf6e]              // 最后一条指令
    [01] ./app-demo() [0xc086]              // 倒数第2调指令
    [02] [0x2aac6000]
    [03] /lib/libc.so.6(memcpy+0x30) [0x2ab516a0]
    [04] ./app-demo() [0xbb62]              // 出问题的地方
    [05] ./app-demo() [0x9e92]
    [06] /lib/libpthread.so.0(+0x61d0) [0x2aacd1d0]
    Dump stack end...
    app exit
    Segmentation fault

    文件分析:

    在虚拟机上使用GNU工具中的addr2line工具获取源码位置

    # addr2line -e app/app-demo 0xbc62 

    # /home/cql/smb/fuxi_h/demo-linux-wjc-20201211/app/main.c:538

    附录:

             SIGHUP 1 A 终端挂起或者控制进程终止 
             SIGINT 2 A 键盘中断(如break键被按下) 正常终止
             SIGQUIT 3 C 键盘的退出键被按下 
             SIGILL 4 C 非法指令 
            SIGABRT 6 C 由abort(3)发出的退出指令,异常终止 
             SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD)
             SIGKILL 9 AEF 杀死进程的终极方法
            SIGSEGV 11 C 无效的内存引用 
            SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 
             SIGALRM 14 A 由alarm(2)发出的信号 
            SIGTERM 15 A 终止信号 
             SIGUSR1 30,10,16 A 用户自定义信号1 给用户做进程间通信,不像其他的处理方法被绑定了
             SIGUSR2 31,12,17 A 用户自定义信号2 
             SIGCHLD 20,17,18 B 子进程结束信号 
             SIGCONT 19,18,25 进程继续(曾被停止的进程) 
             SIGSTOP 17,19,23 DEF 终止进程 
             SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键 
             SIGTTIN 21,21,26 D 后台进程企图从控制终端读 
             SIGTTOU 22,22,27 D 后台进程企图从控制终端写       

  • 相关阅读:
    用电脑Python控制Arduino
    Arduino-LiquidCrystal_I2C 液晶库
    Arduino通讯串口
    nginx statistics in multi-workers
    Nginx RTMP 模块 nginx-rtmp-module 指令详解
    windows下搭建nginx-rtmp服务器
    超实用压力测试工具-ab工具
    (总结)Nginx配置文件nginx.conf中文详解
    NGINX conf 配置文件中的变量大全 可用变量列表及说明
    「自己开发直播」实现nginx-rtmp-module多频道输入输出与权限控制
  • 原文地址:https://www.cnblogs.com/mic-chen/p/14121778.html
Copyright © 2011-2022 走看看