C++ Linux-有时出现分段错误-如何调试

C++ Linux-有时出现分段错误-如何调试,c++,c,linux,segmentation-fault,C++,C,Linux,Segmentation Fault,我有一个Linux程序,它不时以分段错误结束。该程序每小时定期运行一次,但分段故障只是偶尔发生 我在调试时遇到了一个问题,因为如果我使用相同的输入再次运行程序,则不会报告任何错误,并且一切正常 有没有一种方法,如何“报告”发生了哪部分代码错误或是什么导致了问题?通常的方法是让崩溃的程序生成一个corefile,并在崩溃后对此进行分析。确保: 通过在shell中调用ulimit-c unlimited,启动进程,最大核心文件大小足够大(即无限大小) cwd可由segfaulting进程写入 然

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

我在调试时遇到了一个问题,因为如果我使用相同的输入再次运行程序,则不会报告任何错误,并且一切正常


有没有一种方法,如何“报告”发生了哪部分代码错误或是什么导致了问题?

通常的方法是让崩溃的程序生成一个corefile,并在崩溃后对此进行分析。确保:

  • 通过在shell中调用
    ulimit-c unlimited
    ,启动进程,最大核心文件大小足够大(即无限大小)
  • cwd可由segfaulting进程写入
然后,您可以使用


gdb

由于您的代码不会每次都崩溃,因此您也可以使用
回溯
。使用此选项,您可以看到崩溃时的
函数调用堆栈。有很多例子。在我的项目中,我通常使用以下代码进行回溯

/*
*   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;  
}
/*
*从main调用reg_usr2函数
*gcc-rdynamicmyfile.c-o输出
*/
#包括
#包括
#包括
#包括
#包括
#包括
#定义文件名“/tmp/debug”
#定义模式0xFFFF
void dbgprint(int标志,char*fmt,…)
{
if(标志和模式){
char-buf[100];
va_列表;
文件*fp=fopen(文件名,“a”);
va_启动(vlist、fmt);
vsnprintf(buf、sizeof(buf)、fmt、vlist);
瓦乌端(vlist);
fprintf(fp,[%x]->%s\n”,标志,buf);
fclose(fp);
}
}
/**下面是打印回溯跟踪的代码**/
无效打印\堆栈\跟踪()
{
void*数组[20];
大小;
字符**字符串;
尺寸i;
大小=回溯(数组,20);
字符串=回溯符号(数组、大小);
dbgprint(0xFFFF,“获得%zd堆栈帧”,大小);
dbgprint(0xFFFF,“---------------------------”号);
dbgprint(0xFFFF,“-----------回溯-----------------”;
对于(i=0;i
您可以通过捕获SIGSEGV信号生成回溯,并查看应用程序在何处抛出无效访问。 看

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

catchsegv'./程序参数'

还有更好的选择,瓦尔格林

valgrind—工具=无。/program args


打印语句?在
gdb
下运行程序?得到一个核心转储?您尝试过什么?尝试记录变量状态。另外,您可以尝试在
valgrind
@gowrath下运行它。我尝试过打印语句,但这是一个问题,因为错误是随机发生的。所以我试着修理一些东西,后来它运行良好,但第二天,崩溃了again@Yaeger报告没有内存泄漏要生成corefile,我必须使用一些调试信息“构建”程序吗?尽管它很有用(使用
-ggdb
编译),因为corefile包含更多信息(例如,要显示崩溃源代码行的行号),这不是绝对必要的。@MartinPerry不,您必须只增加进程资源限制。请按照Ctx的指示仅在控制台上运行。“ulimit-c unlimited”为什么您需要它,而core dump为您提供了回溯功能。抱歉,我不知道core dump。您能提供有关它的链接吗?感谢您提供的大量信息。但我在一台基于linux的机器上工作,它不支持回溯功能。这就是为什么我只有回溯选项。不,它仅适用于linux机器。请参阅Ctx给出的第二个答案。execinfo可能无法在所有基于linux的系统(如android)上使用,该程序也应与-rdynamic链接