Linux - 有时只分段故障 - 如何调试

时间:2016-12-20 09:16:34

标签: c++ c linux segmentation-fault

我有一个Linux程序,它不时以分段错误结束。程序每小时定期运行,但有时只会发生分段故障。

我有一个问题要调试它,因为如果我使用相同的输入再次运行程序,则不报告任何错误,一切正常。

有没有办法,如何“报告”代码错误发生的部分或导致问题的原因?

3 个答案:

答案 0 :(得分:4)

通常的方法是让崩溃程序生成核心文件并在崩溃后对其进行分析。确保:

  • 最大的corefile-size足够大(即无限),通过调用shell中的ulimit -c unlimited来启动该过程。
  • cwd可以通过segfaulting进程写入。

然后您可以使用

分析文件

gdb <exe> <corefile>

答案 1 :(得分:3)

由于您的代码每次都不会崩溃,因此您也可以使用backtrace。使用此功能,您可以在崩溃时看到function call stack。有很多例子可供使用。在我的项目中,我通常使用以下代码进行回溯。

/*
*   call reg_usr2 function from main
*   gcc -rdynamic myfile.c -o output
*/


#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <execinfo.h>

#define FILE_NAME   "/tmp/debug"
#define MODE        0xFFFF

void dbgprint(int flag, char* fmt, ...)
{
    if(flag & MODE) {
        char buf[100];
        va_list vlist;
        FILE *fp = fopen(FILE_NAME,"a");
        va_start(vlist, fmt);
        vsnprintf( buf, sizeof( buf), fmt, vlist);
        va_end( vlist);
        fprintf(fp,"[%x]->%s\n", flag, buf);
        fclose(fp);
    }
}

/** Here is the code to print backtrace **/
void print_stack_trace ()
{
    void *array[20];
    size_t size;
    char **strings;
    size_t i;

    size = backtrace (array, 20);
    strings = backtrace_symbols (array, size);

    dbgprint(0xFFFF, "Obtained %zd stack frames.", size);
    dbgprint(0xFFFF, "-------------------------");
    dbgprint(0xFFFF, "---------Backtrace-------");

    for (i = 0; i < size; i++)
        dbgprint (0xFFFF, "%s", strings[i]);
    dbgprint(0xFFFF, "-------------------------");

    free (strings);
}

void sig_handler(int signo)
{
    FILE *fp = fopen(FILE_NAME,"a");
    if (signo == SIGUSR2){
        dbgprint(0xFFFF, "received SIGUSR2");
        dbgprint(0xFFFF, "----------------");
    }
    print_stack_trace();
    exit(0);
}

void reg_usr2()
{
    if (signal(SIGUSR2, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGUSR2\n");
}

int main()
{
    reg_usr2(); //should be first line of main after variables

    //Code.....

    return 0;  
}

答案 2 :(得分:3)

您可以通过捕获SIGSEGV信号来生成回溯,并查看您的应用程序在何处引发无效访问。 见https://stackoverflow.com/a/77336/4490542

但是有更简单的解决方案,尝试使用catchsegv运行您的应用程序

  

catchsegv&#39; ./ program args&#39;

和更好的选择,valgrind

  

valgrind --tool = none ./program args