论Segmentation fault
刚开始学c的时候,最头疼的事情是编译总是通不过,郁闷的要死,只要编译通过了,就兴奋的要死。现在,最头疼的事情是什么呢,编译没问题,但是程序跑的时候会出现Segmentation fault!
这个东西非常的恼人,在还是菜鸟阶段不会用gdb的时候,实在解决不了就放弃了,或者用一些对内存管理没有要求的语言来曲线救国了,但是自从开始接触了gdb这类的调试语句之后,发现了出现
Segmentation fault的一些情况,以及解决的方法,写出来总结下:
Segmentation fault 本质就是内存错误,在c/c++语言里,就是指针错误,这个错误产生的原因是你错误的使用了内存,访问了你不该访问的东西,常见的可归类如下:
1.数组越界,你定义了一个大小为10的数组array[10],但是c是从0开始计数的,最后的数组元素是array[9],然后你去访问了a[10],这样就读到了一块不属于你的内存,结果出现了Segmentation fault.
当然,这个是最简单的错误。注意点就会解决。
2.指针的问题。指针本质就是一个数字,IA32下就是一个4字节32位的数字,类似0xAB0011FF这个样子的,如果是x86-64位下的话,就是类似于0xAABBCCDDEEFF0011这种类型8字节64位的,这个数字表示
的是一个内存地址,计算机根据这块内存地址找到内存为此地址的内容,根据其类型读取。这里特别说一下NULL指针,在gdb里,你可以看到NULL实际上就是0x0,当然,前面有其类型,比如(void*) 0x0,这个样子的,
所以,如果你解引用这个NULL指针,其实就是要求计算机去访问内存为0的地址,结果可想而知。当然,有些人觉得自己没蠢到去解引用这个地址,当然,通常情况下这个错误不是这么直接的,但是本质确是一样的,我
举个具体的例子你感受下:
void changept(int* cpt){
cpt=0x48;
printf("in function,the pointer is: %x\n",cpt);
}
int main(){
int *s=0x20AB;
*s=0x332A;
printf("before calling function,the pointer is: %x\n",s);
changept(s);
printf("after calling function,the pointer is: %x\n",s);
return 0;
}
能想像出答案是什么吗,在函数changept中,我们改变了指针cpt 的值,注意是指针本身的值,或者说是这个指针需要指向的地址,但是在函数调用之后,指针显示的地址还是没有改变,但是在函数调用中,我们发现指针的值变了。这当然是因为c语言本身的一个特性,函数是传值调用,你传进去一个指针,注意这个指针是个数字,比如例子中的0x20ab,结果函数在调用时复制了这个值给局部变量(这个局部变量是同类型指针),然后局部变量获得了0x20ab这个地址,接下来让局部变量去指向了新的地址0x48,函数调用结束后这个指针消失,但是原来的指针确还是指向原来的值。好,问题就出在这里,如果我要在函数中为这个指针分配一个内存,比如cpt=(int*)malloc(sizeof(int)*10);注意,从堆上分配的内存让这个局部指针指向了另一个地址,作为参数的指针实际上还是悬空的,没有指向新开辟的地址,如果程序员想用这个悬空指针(他可能认为已经获得了内存)去访问这个开僻的新内存,那么实际上他访问的还是原来的内存,这样就会造成指针的错误引用,造成Segmentation fault这样的错误。所以,不要在函数中改变指针本身的值
解决上述问题的方法很简单,把函数changept的参数改成(int** cpt),*cpt=0x48,调用的时候就是changept(&s). 结果就正确了. 为啥呢,这个很简单,你传进去的是存储这个指针的内存地址,也是个数字,比如0x88, 0x88所指向的内存空间里存储着这个指针0x20AB,然后呢,局部变量获得了0x88这个地址,也指向了指针0x20ab,解引用0x88,获取0x20ab的值,并改为0x48, 此时指向0x20ab的指针已经被修改了,于是函数调用后的结果也变了。这个时候,假如要为原来指向0x20ab的指针申请了新的地址,那么指针也就指向了新的地址,这个时候访问这段开辟出的地址就没有问题了。所以,要想改变指针的值,要给函数传入这个指针的地址,或者说是指向指针的指针。
3. 数值类型,尽量不要用unsigned这类无符号类型的整数,比如你申请一块地址,malloc(sizeof(int)*a),如果a=-1的话(IA32 下是 补码 表示0xFFFFFFFF,unsigned a 会导致这个数变成一个超大的数,当然这个数还是0xFFFFFFFF,但是作为无符号来解读的话就是一个超大的数了,是2^32-1这样一个数,堆上分配不出这么大的空间,导致程序出现意想不到的问题。此外,如果你的程序在一个循环内,如果用无符号的数去和类似负数之类的比,可能产生死循环或者内存越界。
4.字符串,其实主要就是注意,如果你用strlen之类的函数,记得分配内存的时候要加1,因为strlen不包含‘\0'在内,否则还会产生越界,造成segmentation fault.
其实以上问题避免了,应该会杜绝90%以上的段错误,但是,更本质的是,你应该多学习计算机底层的机制,毕竟,c的强大就是它既有高级语言的便捷,也有底层语言的强大,而了解指针也就相当与掌握了c语言的核心,终将帮助你提高自身的编程修养!
论Segmentation fault的更多相关文章
- Caffe Python MemoryDataLayer Segmentation Fault
转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ 因为利用Pyhon来做数据的预处理比较方便,因此在data_l ...
- php php-5.6.4.tar.bz2 apache 兼容问题 child pid 27858 exit signal Segmentation fault
环境 [root envirotar]# uname -a Linux i2..el6.x86_64 # SMP Thu Jul :: UTC x86_64 x86_64 x86_64 GNU/Lin ...
- Segmentation fault (core dumped)
问题: 在Linux中实现快速排序时,没有加入终止条件,结果出现Segmentation fault (core dumped)这个问题,Segmentation fault (core dumped ...
- centos yum Segmentation fault 问题解决办法
今儿在centos 使用yum 安装软件时出现了 ”Segmentation fault“ 错误提示,google一大把执行 yum clean all 命令后,再执行还是没用,最后把 zlib.x. ...
- 内存分配与Segmentation fault
为了方便使用,我做了如下结构体的嵌套使用: struct operation{ int num; char name[100]; char owner[100]; char msg[100];}; s ...
- qt 单文档程序关闭时在delete ui处出现segmentation fault
做了个显示图片的单文档程序. qt 单文档程序关闭时在delete ui处出现segmentation fault. 调试发现调用两次mainwindow析构函数. http://blog.csdn. ...
- linux Ubuntu(Segmentation fault)段错误出现原因及调试方法
在linux下编译了一个程序,尝试运行的时候出现: Segmentation fault (core dumped) 初步确认为...完全不知道是什么玩意. 于是找度娘了. ----------- ...
- 记一次PHP“Segmentation fault”调试经历
遇到的问题: 在linux上安装php5.5.26.phalcon2.0扩展.xhprof扩展,均正常安装,并可单独运行.但放在一起运行时出现“Segmentation fault”错误.注:xhpr ...
- segmentation fault
今天在hanoi问题上出现了segmentation fault 在gcc编译的过程中 没出现error,然而程序运行到一半就出现segmentation fault: 上网发现 这条语句是非法的内存 ...
随机推荐
- hbase基础-系统架构
HBase 系统架构 HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列 ...
- eclipse @override注解出错
在工程中新建了一个接口,定义了一个methodA,然后写一个接口类实现该方法,并加上@override注解 项目提示@override出错,必须覆盖原方法XXX,解决办法 1)项目右键-project ...
- [DFNews] Cellebrite UFED Logical/Physical Analyzer 3.8.1 维护性更新
Maintenance Release Cellebrite has released a maintenance version of UFED Physical / Log ...
- lighttpd配置
1.lighttpd.conf server.modules = ( "mod_access", "mod_alias", "mod_compress ...
- flex acionscript png图片去除多余空白,生成合适大小图片
//最小矩形(非透明最小区域) public static function getMinRect(target:BitmapData):Rectangle{ return target.getC ...
- 在windows编译MariaDB
OS: Windows XP sp3 IDE: VS2010 MariaDB: V5.5 (到目前为止2016.5,中文域(.cn)只有清华大学 TUNA 镜像源可用) (.tar.gz为源码:.zi ...
- 3、NAT
<计算机网络(第5版)>P173 P182
- Linux 网络基本配置
一.Linux网络配置文件 1. /etc/sysconfig/network-scripts/ifcfg-eth0 文件 在Red Hat系统中,系统网络设备的配置文件保存在/etc/syscon ...
- 样式:让div里的两个控件在一行的操作
table的td里如果放一个text,希望在右侧再放一个按钮,让这两个控件在一行,但是放了之后总是底部不能对齐,这样的话,加上下边这句样式就可以了 position:relative; top:17p ...
- LR12.53—第7课:分析场景
第7课:分析场景 在前面的课程中,您学习如何设计,控制和执行方案运行.一旦您已加载您的服务器,你要分析的运行,并确定需要被淘汰,以提高系统性能的问题. 在图表和报告中有关方案的性能您的分析会议上提出的 ...