C程序中的段错误跟踪

来源:互联网 发布:淘宝做什么产品赚钱 编辑:程序博客网 时间:2024/06/05 20:43
想要准确的跟踪段错误需要以下几点
1、C程序中加入信号捕获和段错误地址打印代码
2、编译程序时,加入 -g -DDEBUG 选项
3、段错误发生时,利用打印出的地址,使用addr2line追踪,或者nm工具追踪。

下面分别说明:
1、段错误捕获及地址打印

void SIGSEGV_handler( int signum, siginfo_t* sig_info, void* context)
{
    void *str_array[16];
    int size;
    char **str = (char **)NULL;
    void *pnt = NULL;
    ucontext_t* uc = (ucontext_t*) context;
    int i;

    printf("\n****** Segmentation fault caught ....\n");

    size = backtrace (str_array, 15);
    str = backtrace_symbols (str_array, size);
    pnt = (void*) uc->uc_mcontext.arm_lr;
    str_array[1] = pnt;
    printf("Faulty address is %p, called from %p\n", sig_info->si_addr, pnt);

    printf ("Totally Obtained %zd stack frames. signal number =%d \n", size, signum);
    if(signum == SIGSEGV)
    {
       printf(" Signal number = %d, Signal errno = %d\n",
        sig_info->si_signo, sig_info->si_errno);
       switch(sig_info->si_code)
       {
        case 1: printf(" SI code = %d (Address not mapped to object)\n",
          sig_info->si_code);
         break;
        case 2: printf(" SI code = %d (Invalid permissions for \
             mapped object)\n",sig_info->si_code);
          break;
        default: printf("SI code = %d (Unknown SI Code)\n",sig_info->si_code);
        break;
       }
       printf(" Fault addr = %p \n",sig_info->si_addr);
    }
    printf("[bt] Execution path:\n");
    for (i = 0; i < size; i++)
    {
     printf ("[bt] %s\n", str[i]);
    }
    exit(0);
}

/*initialize the running environment*/
static void env_init()
{
    struct sigaction sa;

    sa.sa_sigaction = (void *)SIGSEGV_handler;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_SIGINFO;

    sigaction(SIGSEGV, &sa, NULL);
}

int main()
{


    /*run env initial*/
    env_init();

    return 0;
}


举例:
当段错误发生时,就会输出如下打印:

****** Segmentation fault caught ....
Faulty address is 0x5, called from 0x6e6d8
Totally Obtained 0 stack frames. signal number =11
 Signal number = 11, Signal errno = 0
 SI code = 1 (Address not mapped to object)
 Fault addr = 0x5


0x6e6d8 就是发生段错误的地方



2、程序编译

在Makefile中加入 -g -DDEBUG
编译好之后,可使用 nm -n a.out 来查看是否有符号表输出
如果加了 -g ,但是nm命令还是打印 no symbols,可能是makefile中加了strip,去掉strip即可


3、使用addr2line追踪段错误

以上面第一条中举例的段错误地址为例
直接在编译平台(ubuntu)中,输入
addr2line 0x6e678 -e a.out -f,直接定位在哪个函数的哪行

我的段错误就是发生在函数的参数中,使用了一个野指针导致的。
0 0
原创粉丝点击