刚开始学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的更多相关文章

  1. Caffe Python MemoryDataLayer Segmentation Fault

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ 因为利用Pyhon来做数据的预处理比较方便,因此在data_l ...

  2. 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 ...

  3. Segmentation fault (core dumped)

    问题: 在Linux中实现快速排序时,没有加入终止条件,结果出现Segmentation fault (core dumped)这个问题,Segmentation fault (core dumped ...

  4. centos yum Segmentation fault 问题解决办法

    今儿在centos 使用yum 安装软件时出现了 ”Segmentation fault“ 错误提示,google一大把执行 yum clean all 命令后,再执行还是没用,最后把 zlib.x. ...

  5. 内存分配与Segmentation fault

    为了方便使用,我做了如下结构体的嵌套使用: struct operation{ int num; char name[100]; char owner[100]; char msg[100];}; s ...

  6. qt 单文档程序关闭时在delete ui处出现segmentation fault

    做了个显示图片的单文档程序. qt 单文档程序关闭时在delete ui处出现segmentation fault. 调试发现调用两次mainwindow析构函数. http://blog.csdn. ...

  7. linux Ubuntu(Segmentation fault)段错误出现原因及调试方法

      在linux下编译了一个程序,尝试运行的时候出现: Segmentation fault (core dumped) 初步确认为...完全不知道是什么玩意. 于是找度娘了. ----------- ...

  8. 记一次PHP“Segmentation fault”调试经历

    遇到的问题: 在linux上安装php5.5.26.phalcon2.0扩展.xhprof扩展,均正常安装,并可单独运行.但放在一起运行时出现“Segmentation fault”错误.注:xhpr ...

  9. segmentation fault

    今天在hanoi问题上出现了segmentation fault 在gcc编译的过程中 没出现error,然而程序运行到一半就出现segmentation fault: 上网发现 这条语句是非法的内存 ...

随机推荐

  1. (.text+0x12): undefined reference to `rpl_fprintf'

    问题1:(.text+0x12): undefined reference to `rpl_fprintf'解决办法:在yacc前面添加%{#undef yyerrorvoid yyerror (ch ...

  2. .NET 平台下的插件化开发内核(Rabbit Kernel)-转

    什么是RabbitHub? RabbitHub 是专门针对 .NET 平台所设计.研发的一套相对完整的插件开发框架,它是由一个内核两大框架多个组件及一系列的开发时支持而构成. RabbitHub 架构 ...

  3. dubbo工作原理

    part -- 外挂1.dubbo借助spring的schema启动和初始化 1.1 spring扫描所有jar下META-INF的spring.handlers和spring.schemas. 1. ...

  4. Python基础语法,基本数据类型及相关操作

    ---恢复内容开始--- python文件 文件开头要有  #!/usr/bin/ python        --在linux中是告诉系统phthon的路径是在/usr/bin/ python目录下 ...

  5. 从零开始系列--R语言基础学习笔记之一 环境搭建

    R是免费开源的软件,具有强大的数据处理和绘图等功能.下面是R开发环境的搭建过程. 一.点击网址 https://www.r-project.org/ ,进入"The R Project fo ...

  6. Python基础篇【第6篇】: Python装饰器

    装饰器 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类, ...

  7. 黑马程序员_ C语言基础(二)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 概览 今天基础知识分为以下几点内容(注意:循环.条件语句在此不再赘述):   1.Hello W ...

  8. win8.1中EZDML输入中文显示问号问题

    在win8.1下使用EZDML,发现无法输入中文,解决办法如下:   打开控制面板--语言   删除美式键盘 然后就可以正常输入中文了 其实就是win8.1把美式键盘默认放在中文语言中,导致的输入问题 ...

  9. 解决window2012 IIS8 配置的网站无法下载exe文件的问题

    window2012 IIS8 配置网站下载exe文件.解决window2012 IIS8 配置的网站无法下载exe文件的问题 配置好网站后,无法下载网站上的exe文件,zip文件确可以下载的.右键点 ...

  10. fgtyn

    http://www.studiocleo.com/projects/ballettechnique/one_11.html