关于“段错误”个人小结

来源:互联网 发布:3个数最小公倍数算法 编辑:程序博客网 时间:2024/04/30 00:36

1.什么是段错误?

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

通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的。

2.那什么操作会引起段错误呢?

粗略的分一下类:

1)往受到系统保护的内存地址写数据

有些内存是内核占用的或者是其他程序正在使用,为了保证系统正常工作,所以会受到系统的保护,而不能任意访问。

2)内存越界(数组越界,变量类型不一致等)

3)其他

例如:

<1>定义了指针后记得初始化,在使用的时候记得判断是否为NULL

<2>在使用数组的时候是否被初始化,数组下标是否越界,数组元素是否存在等

<3>在变量处理的时候变量的格式控制是否合理等

3.那么我们如何去发现程序中的段错误呢?

通过学习前人的经验和开发的工具,不断的尝试和研究,找出更恰当的方法来避免、发现并处理它。对于一些常见的地方,我们可以避免,对于一些“隐藏”的地方,我们要发现它,发现以后就要及时处理,避免留下隐患。

用gdb来调试,在运行到段错误的地方,会自动停下来并显示出错的行和行号,gdb也是最常用的,如果需要用gdb调试,记得在编译的时候加上-g参数。

 

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2009-06/20399.htm

 

 

 段错误个人理解就是访问了不可访问的内存!要么这个内存去不存在,要么就是受操作系统保护!
个人遇到段错误的几次都是由于指针的使用,没有考虑周全。。。比如访问了一个根本不存在的区域,比如:

#include<stdio.h>
#include<dirent.h>

int main(int argc,char *argv[])
{
    DIR  *dp;
    struct dirent *dirp;
    if(argc!=2) //只列出了命令时,提示输入文件夹名称
    {    printf("请输入想要列出的文件夹名称!\n");
        //exit(1);//此处不退出则结果包含段错误!!-------->KEY
    }
    if((dp=opendir(argv[1]))==NULL)//如果此处不存在argv[1],则显示“段错误”
        printf("不能打开该目录!");
    while((dirp=readdir(dp))!=NULL)
        printf("%s\n",dirp->d_name);
    closedir(dp);
    exit(0);
}

这段程序功能是模拟ls命令,显示文件夹下面的文件名,

gcc -o myls myls.c
**********
./myls  /media/yule
.....   //显示娱乐盘符下的内容
************
./myls 回车
请输入想要列出的文件夹名称!
段错误

分析下:此处的命令行参数个数为1,argv[1]根本没有被赋值,所以结果可想而知,就是指针使用上的常见错误!

至于受操作系统保护一说,我想到了一个简短的代码:

#include <stdio.h>
int main()
{       
    int i = 0;     
    scanf ("%d", i); /* should have used &i */       
    printf ("%d\n", i);      
    return 0;
}
$:gcc -o test test.c
$:./test
10
段错误

通过gdb调试我发现,问题所在就是,i被初始化为0,而scanf一句此时功能是想地址为i的内存输入一个值,也就是说我们正在尝试想地址为0 的区域输入一个值!

其实第一个也可以说成数组越界,都会产生段错误,我都遇到过!

以上是我的一点点体会理解,不知道说的有没有什么不妥的,第一次发技术帖(自认为)希望借此抛砖引玉阿~小弟在此谢过各位拉~

原创粉丝点击