简单的说,产生段错误就是访问了错误的内存段,一般就是没有权限,或者根本就不存在对应的物理内存,尤其常见的就是访问0地址。
一般来说,段错误就是指访问的内存超过了系统所给这个程序的内存空间,通常这个值是由gdbr来保存的,也是一个48位的器存器,其中的32位是保存由它指向的gdt表,后13位包括了程序是否在内存中以及程序在cpu中的运行级别,指向的gdt是由以64位为一个单元的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址及与此相应的段限和页面交换还有程序运行级别还有内存粒度等信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是“段错误”就出现了。。
在编程中一下几类做法容易导致段错误,基本是错误的应用指针引起的
(1)访问系统数据区,尤其是往系统保护的内存地址写数据,最常见的就是给一个指针0地址
(2)内存越界(数组越界、变量类型不一致)访问到不属于你的内存区域
解决方法:我们在用C/C++语言编写程序时,内存管理的绝大多数工作都需要我们来做。事实上,内存管理是一个比较繁琐的工作,无论你有多牛逼,经验有多丰富,难免会犯一些小的错误,虽然一些下的错误是比较容易消除的,但是手工的“除虫”(bug),往往效率低且让人讨厌,接下来就说说如何快速的定位“段错误”。
1.以下面的程序为例,来介绍几种调试方法。
void funtion(void)
{
char *ptr = 0x00;
*ptr = 0x00;
}
int main()
{
funtion();
return 0;
}
以上代码的bug应该很明显,因为它尝试访问地址为0的内存区域,而这个区域通常是不可以访问的,当然就会出错。下面是编译后的结果:
leiyu@leiyu:~/shishi$ ./a.out
段错误 (核心已转储)
1.利用gdb逐布查找段错误(相信这种方法大家都比较熟悉)首先我们需要一个带有调试信息的可执行程序,所以我们加上“
-g-rdynamic”的参数进行编译,然后用gdb调试这个新编译的程序,具体看下面的:
好像不用一步一步调试就可以找到错误所在的位置,是不是挺方便的!
2.分析Core文件
Core是什么?(来自man 5 core)
不过挺奇怪的,在自己的系统上并没有找到,原来是禁止了core文件的产生,查看一下果然是这样,将系统的core文件的大小限制在512K大小,在试试: