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