Linux系统中段错误信号sigsegv的捕获和调试使用

本文介绍了在Linux系统中通过捕获信号sigsegv信号debug segmentation fault的方法。

要在程序的执行过程中能捕获段错误发出的信号sigsegv,需要在程序的开始的时候注册信号的处理函数signal(SIGSEGV, sigsegv_handler);并且在信号的处理函数sigsegv_handler中需要调用系统调用backtrace和bacetrace_symbols打印出回溯信息。接下来还需要通过objdump 的命令将程序反汇编成一个.s的汇编文件。然后根据回溯信息和汇编文件的内容从而定义出产生段错误的位置。

下面是一个示例的程序,程序在执行几秒后就会因为向一个空指针中赋值而产生段错误。

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

#define BACKTRACE_SIZE 16

void ShowStack(void)
{
	int i;
	void *buffer[BACKTRACE_SIZE];

	int n = backtrace(buffer, BACKTRACE_SIZE);
	printf("[%s]:[%d] n = %d\n", __func__, __LINE__, n);
	char **symbols = backtrace_symbols(buffer, n);
	if(NULL == symbols){
		perror("backtrace symbols");
		exit(EXIT_FAILURE);
	}
	printf("[%s]:[%d]\n", __func__, __LINE__);
	for (i = 0; i < n; i++) {
		printf("%d: %s\n", i, symbols[i]);
	}

	free(symbols);
}

void sigsegv_handler(int signo)
{
	if (signo == SIGSEGV) {
		printf("Receive SIGSEGV signal\n");
		printf("-----call stack-----\n");
		ShowStack();
		exit(-1);
	} else {
		printf("this is sig %d", signo);
	}
}

int main(int argc, char *argv[])
{
	printf("The code compile date:[%s]:[%s] !!!\n", __DATE__, __TIME__);
	signal(SIGSEGV, sigsegv_handler);
	int i = 0;
	char *p = NULL;
	while(1)
	{
		printf("%s:[%s]:[%d]\n", __DATE__, __func__, __LINE__);
		sleep(1);
		i++;
		if(3 == i){
			*p = 0x55;
		}
	}
	return -1;
}

下面是在Ubuntu中执行的效果:

The code compile date:[Jun 19 2020]:[15:44:07] !!!
Jun 19 2020:[main]:[49]
Jun 19 2020:[main]:[49]
Jun 19 2020:[main]:[49]
Receive SIGSEGV signal
-----call stack-----
[ShowStack]:[15] n = 6
[ShowStack]:[21]
0: ./test(ShowStack+0x1c) [0x400a59]
1: ./test(sigsegv_handler+0x2a) [0x400b62]
2: /lib/x86_64-linux-gnu/libc.so.6(+0x36cb0) [0x7f2547ea2cb0]
3: ./test(main+0x7c) [0x400bfe]
4: /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f2547e8df45]
5: ./test() [0x400979]

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值