段错误以及调试方法

Posted SimonKly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了段错误以及调试方法相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

常见内存错误

(1)内存分配(malloc, new)未成功,却使用了它。

解决方法:在使用内存之前检查指针是否为NULL

(2)内存分配成功,但是没有初始化。在定义数组时养成赋0值的习惯。

(3)内存分配成功,也初始化了,操作越过了内存的边界。

(4)忘记释放内存,造成内存泄漏

(5)释放了内存后继续使用,有三种情况:

  • 程序中的对象调用过于复杂,比如:
int *a = new int[10];
int *b = a;

delete b;//已经将a所指向的内存释放
delete a;//又释放一遍,会出现错误
  • 函数return一个局部变量指针,函数结束申请的栈中的资源就会被回收
  • 使用free和delete释放内存后,没有将指针设置为NULL,导致产生野指针

段错误:

简而言之,产生段错误就是访问了错误的内存段,一般是由于没有权限,或者根本就不存在对应的物理地址,尤其常见的是访问0地址。

一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存控件,通常这个值由gdr来保存的,它是一个48为的寄存器,其中的32位用来保存由它指向的gdt表;后13位用来保存相应于gdt的下标;最后3位包括了程序是否在内存中,以及程序的在CPU中的运行级别。指向的gdt是一个以64位单位的表,在这张表中保存着程序运行的代码段、数据段的起始地址,以及与此相应的段限和页面交换还有程序运行级别,还有内存粒度等的信息。一旦这个程序发生了越界访问,CPU就会产生相应的异常保护,于是segment fault就出现了。

方法一:利用gdb逐步查找段错误

GDB调试方法

 方法二:分析core文件

 本人使用的RedHat 5的系统,禁止了core文件的生成。

使用ulimit -c查看一个系统core的大小限制

ulimit -c unlimited无限制

gcc -g test.c -o  test

./test

出现段错误会显示 (段错误(core dump))

gdb test core

方法三:利用backtrace和objdump进行分析

 1 #include <stdio.h>
 2 #include <execinfo.h>
 3 #include <stdlib.h>
 4 #include <signal.h>
 5 
 6 void dummy_function(void)
 7 {
 8     unsigned char * ptr = 0x00;
 9     *ptr = 0x00;
10 }
11 
12 void dump(int signo)//利用backstrace来打印信息
13 {
14     void *array[10];
15     size_t size;
16     char **strings;
17     size_t i;
18     size = backtrace(array, 10);
19     strings = backtrace_symbols(array, size);
20     printf("Obtained %zd stack frames.\\n", size);
21 
22     for (i = 0; i < size; i++)
23     {
24         printf("%s\\n", strings[i]);
25     }
26 
27     free(strings);
28     exit(0);
29 }
30 
31 
32 int main()
33 {
34     signal(SIGSEGV, &dump);
35     dummy_function();
36 
37     return 0;
38 }

再结合objdump -d a.out反汇编,找出出错地址在哪个函数中(实在是看不懂,但是了解一下吧)

 

 

 

 

 

 

以上是关于段错误以及调试方法的主要内容,如果未能解决你的问题,请参考以下文章

linux c 用户态调试追踪函数调用堆栈以及定位段错误

段错误产生原因及简单的调试方法

调试难以捉摸的段错误

VS 2010 中的 C++ 调试访问冲突

PHP代码-psysh调试代码片段工具

在“设置”片段中夸大类PreferenceScreen的错误