论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: 上网发现 这条语句是非法的内存 ...
随机推荐
- web api 开发记录
1. 修改 api 返回时间格式 //配置返回的时间类型数据格式 GlobalConfiguration.Configuration.Formatters.JsonFormatter.Serializ ...
- BigInger isProbablePrime
JAVA BigInteger 成员函数: isProbablePrime public boolean isProbablePrime(int certainty) 如果此 BigInteger 可 ...
- Nexus3.0.0+Maven的使用(一)
1.Nexus介绍 Nexus是一个强大的Maven仓库管理器,它极大地简化了自己内部仓库的维护和外部仓库的访问.利用Nexus你可以只在一个地方就能够完全控制访问 和部署在你所维护仓库中的每个Art ...
- 每天一个 Linux 命令(20):find命令之exec
find是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释: -exec 参数后面跟的是command ...
- 一个服务器要绑定多个HTTPS站点
默认情况一个服务器的IIS只能绑定一个HTTPS也就是443端口 要实现多个站点对应HTTPS只能更改IIS配置 地址:C:\Windows\system32\inetsrv\config\appli ...
- Django 之 查看执行的sql语句
前提: 我的app名称为core,models.py内容如下: # coding:utf-8 from django.db import models # Create your models her ...
- [Linux编程] module_param()函数学习笔记
在读TCP cubic源码中,遇到了module_param(),网上查到的资料如下: 在用户态下编程可以通过main()来传递命令行参数,而编写一个内核模块则可通过module_param()来传递 ...
- STL之set
set都快不会用了...整理下... 应该注意的是set中的值是不能相同的...和map一样... 原文链接:http://blog.csdn.net/wangran51/article/detail ...
- UNIX网络编程-Select模型学习
1.相关接口介绍 1.1 select ---------------------------------------------------------------------- #include ...
- html基础 链接
使用图像来作链接: (链接标签中嵌套图片标签) <html> <body> <p> 您也可以使用图像来作链接: <a href="/example/ ...