什么是段错误? 所谓的段错误 就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表, 后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了 通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的。 下面是一些段错误例子:
1.访问不存在的内存地址 如下面代码,p没有申请空间就直接拷贝数据: int main(int argc, char *argv[]) { char *p = NULL; strncpy(p, "abc", 3);//p没有申请空间就直接使用 return 0; } 2.访问只读的内存地址 错误做法:往字符串常量空间拷贝新的数据 int main(int argc, char *argv[]) { char *p = "test"; strcpy(p, "TEST1"); return 0; } 3.访问系统保护的内存地址 int main(int argc, char *argv[]) { int *p = (int *)0; *p = 100; return 0; } 4.栈溢出 int main(int argc, char *argv[]) { main(argc, argv); } 5.内存越界(数组越界,变量类型不一致等) int main() { char test[1]; printf("%c", test[1000000000]); return 0; } 这里是比较极端的例子,但是有时候可能是会出现的,是个明显的数组越界的问题 或者是这个地址是根本就不存在的 下面我给大家介绍两种常用的段错误调试方法 1.使用printf输出调试信息 这个是看似最简单但往往很多情况下是十分有效的调试方式,也许我们用的最多的调试方式。简单来说,就是在程序的重要代码附近加上printf输出信息,这样可以跟踪并打印出段错误在代码中最可能出现的位置。 以下面这段错误代码为例: 现在在代码中添加printf调试信息: int main(int argc, char *argv[]) { printf("line:%d\n", __LINE__); //单纯打印代码行数 char *p = NULL; printf("line:%d\n", __LINE__); //单纯打印代码行数 strncpy(p, "abc", 3); // /p没有申请空间就直接使用 printf("line:%d\n", __LINE__); //单纯打印代码行数 return 0; } 2. 使用gcc和gdb 想详细了解gdb调试工具可以访问下面的网址: 调试步骤: 1、为了能够使用gdb调试程序,在编译阶段加上-g参数,还是以下面这段错误代码为例: int main(int argc, char *argv[]) { char *p = NULL; strncpy(p, "abc", 3);//p没有申请空间就直接使用 return 0; } 编译代码添加-g选项 gcc -g -o xxx xxx.c 编译程序,然后用gdb调试:
|