Linux-有时仅分割故障 - 如何调试

Linux - segmentation fault only sometimes - how to debug

本文关键字:何调试 调试 分割 故障 Linux-      更新时间:2023-10-16

我有一个Linux程序,该程序不时以分段故障结束。该程序每小时定期运行,但是分段故障有时仅发生。

我有一个问题要调试此问题,因为如果我再次使用相同的输入运行程序,则不会报告错误,一切都可以。

有没有办法,如何"报告"代码错误的哪一部分或引起问题的原因?

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

  • 最大的核心尺寸大小足够大(即 unlimited ),通过在shell中调用 ulimit -c unlimited,这开始了该过程。
  • CWD由segfaulting Process进行了写作。

然后您可以用

分析文件

gdb <exe> <corefile>

由于您的代码没有每次崩溃,因此您也可以使用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]->%sn", 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 SIGUSR2n");
}
int main()
{
    reg_usr2(); //should be first line of main after variables
    //Code.....
    return 0;  
}

您可以通过捕获Sigsegv信号来生成回溯,并查看应用程序在何处投掷无效的访问权限。请参阅https://stackoverflow.com/a/77336/4490542

但是有更容易的解决方案,请尝试使用CatchSegv

运行您的应用程序

catchsegv'./program args'

和更好的替代方案,valgrind

valgrind -tool = none./program args