程序退出,段错误segment default问题定位

1、backtrace和backtrace_symbols函数

这两个函数的主要作用是打印出函数的调用方式,即压栈的信息。

使用方法:

static void dump(void)
{
 void *buffer[30] = {0};
 size_t size;
 char **strings = NULL;
 size_t i = 0;


 size = backtrace(buffer, 30);
 fprintf(stdout, "Obtained %zd stack frames.nm\n", size);
 strings = backtrace_symbols(buffer, size);
 if (strings == NULL)
 {
  perror("backtrace_symbols.");
  exit(EXIT_FAILURE);
 }
 
 for (i = 0; i < size; i++)
 {
  fprintf(stdout, "%s\n", strings[i]);
 }
 free(strings);
 strings = NULL;
}

这两个函数是获取调用函数的栈的信息,如果遇到段错误的时候根据退栈信息大体能定位出是在哪个函数或者什么地方出的问题。

2、初始化信号量

void initSegvCatch()
{    
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = OnSIGSEGV;
act.sa_flags = SA_SIGINFO;
if(sigaction(SIGSEGV, &act, NULL)<0 )
{
perror("sigaction:");
}
}

3、回调函数

static void dump(void)
{
 void *buffer[30] = {0};
 size_t size;
 char **strings = NULL;
 size_t i = 0;


 size = backtrace(buffer, 30);
 fprintf(stdout, "Obtained %zd stack frames.nm\n", size);
 strings = backtrace_symbols(buffer, size);
 if (strings == NULL)
 {
  perror("backtrace_symbols.");
  exit(EXIT_FAILURE);
 }
 
 for (i = 0; i < size; i++)
 {
  fprintf(stdout, "%s\n", strings[i]);
 }
 free(strings);
 strings = NULL;


}

static void OnSIGSEGV(int signum, siginfo_t *info, void *ptr)
{    
printf("\n-------------------------- 进程挂掉时的MAPS文件 --------------------------\n");
/* 动态链接库的映射地址是动态的,需要将maps文件打印出来 */
char file[64], buffer[1032];
pid_t pid = getpid();
snprintf(file, sizeof(file), "/proc/%d/maps", pid);
FILE *fp = fopen(file, "r");
if (NULL != fp)
{
while(fgets(buffer, 1024, fp))
{
fputs(buffer, stdout);
}
}
else
{
printf("读取MAPS文件失败!\n");
}
debuging("-------------------------------------------------------------------------\n\n");
debuging("---------------------------进程挂掉时的堆栈信息--------------------------\n");
static int iTime = 0;
if (iTime++ >= 1)
{ /* 容错处理:如果访问 ucontext_t 结构体时产生错误会进入该分支 */
debuging("ReEnter %s is not allowed!\n", __FUNCTION__);
abort();
}
dump();
debuging("-------------------------------------------------------------------------\n\n");
abort();
}


4、说明

    通过信号量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Segmentation fault(段错误)是一种常见的程序错误,通常是由于访问了无效的内存地址或者内存越界导致的。定位Segmentation fault问题可以通过以下几个步骤来进行: 1. 编译选项:在编译程序时,可以使用一些选项来帮助定位Segmentation fault问题。例如,在gcc编译器中,可以使用"-g"选项来生成调试信息,使用"-fsanitize=address"选项来检测内存错误。 2. 调试工具:使用调试工具可以帮助我们逐步执行程序并查看变量的值,以便找到引发Segmentation fault的原因。常用的调试工具有gdb(GNU调试器)和valgrind。 - 使用gdb:可以通过在命令行中输入"gdb <可执行文件名>"来启动gdb调试器。然后可以使用"run"命令来运行程序,并在Segmentation fault发生时暂停程序的执行。使用"backtrace"命令可以查看函数调用栈,定位到引发错误的代码行。 - 使用valgrind:可以通过在命令行中输入"valgrind <可执行文件名>"来运行程序,并检测内存错误。valgrind会输出详细的错误信息,包括引发Segmentation fault的代码行。 3. 代码审查:仔细检查代码,特别是涉及指针操作和数组访问的地方。常见的引发Segmentation fault的原因包括: - 空指针引用:使用了一个未初始化或者已经释放的指针。 - 内存越界:访问了数组或者其他数据结构的越界位置。 - 野指针:使用了一个已经释放的指针。 - 栈溢出:函数调用过深导致栈空间不足。 以上是定位Segmentation fault问题的一般步骤和方法,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值