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

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

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

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

#include 
#include 
#include 
#include 
#include 

#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]

 

你可能感兴趣的:(linux系统编程,bug调试)