3、利用backtrace进行分析
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <execinfo.h>
- void func0(void)
- {
- printf("This is func0\n");
- int *p = NULL;
- *p = 1234;
- }
- void func1(void)
- {
- printf("This is func1\n");
- func0();
- }
- void func2(void)
- {
- printf("This is func2\n");
- func1();
- }
- void dump(int signo)
- {
- void *array[100];
- size_t size;
- char **strings;
- size = backtrace(array, 100);
- strings = backtrace_symbols(array, size);
- printf("Obtained %zd stacks.\n", size);
- for(int i = 0; i < size; i++)
- {
- printf("%s\n", strings[i]);
- }
-
- free(strings);
- exit(0);
- }
- int main(int argc, char **argv)
- {
- printf("==================segmentation fault test5==================\n");
- signal(SIGSEGV, &dump);
- func2();
- return 0;
- }
当程序发生段错误时,内核会向程序发送SIGSEGV信号。dump为SIGSEGV信号处理函数,其实现用到了execinfo.h里的两个函数:
- int backtrace(void **buffer,int size);
- char ** backtrace_symbols (void *const *buffer, int size);
backtrace函数用于获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针列表。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小 在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址。
backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组。参数buffer应该是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace的返回值)。函数返回值是一个指向字符串数组的指针,它的大小同buffer相同。
每个字符串包含了一个相对于buffer中对应元素的可打印信息。它包括函数名,函数的偏移地址,和实际的返回地址。注意:该函数的返回值是通过malloc函数申请的空间,因此调用者必须使用free函数来释放指针。如果不能为字符串获取足够的空间函数的返回值将会为NULL。
以上就是本次介绍的三种定位段错误问题的方法,可以定位不同程度的问题。
|