Segmentation fault到底是何方妖孽

    前两天和阿彬 扯淡的时候(注意不是扯蛋 ),他说自己一个礼拜解决了三个Core dump,华丽丽之极,让我对其敬仰、膜拜之情如滔滔之江水,绵绵不绝 今天我也来谈一下Linux环境下开发时经常遇到的“Segmetation fault”的一点点个人看法,也算是抛砖引玉了。
   
(备注:我的glibc版本是2.12,GCC版本4.4.6,内核版本2.6.32-279)
   Linux
上开发时最恼火的就是遇到“ Segmetation Fault ”错误。为什么这么说,很多人看到这个错误后心里第一反应是程序访问的非法的内存,导致其被操作系统强行终止。这固然没错,可这里有个比较模糊的概念了:什么叫“非法”的内存?

   
程序运行时,每个进程都有自己的虚拟地址,理论上说进程应该可以随便使用才对,为什么还会出现这个错误呢?这里就涉及到程序的装载过程及原理。
   
先澄清几个概念:
   
程序:一般是一组 CPU 指令的集合构成的文件,静态存储在诸如硬盘之类的存储设备上。
   
进程:当一个程序要被计算机运行时,就是在内存中产生该程序的一个运行时实例,我们就把这个实例叫做进程。
   
装载:上述从硬盘上的静态“程序”到内存中动态的“进程”之间的转变过程就叫做装载。往通俗里讲,就是启动一个进程。

   
本文的主要目的是在简单了解进程的内存布局的情况下,从装载的过程入手,深入了解一下 Segmetation Fault 在操作系统层面是如何产生的,以及程序开发过程中应该如何避免这样的错误。
   
众所周知 Linux 中可执行文件的格式是 ELF ,其实编译过程中的中间文件 *.o 文件、动态共享库 *.so 文件也是 ELF 格式的。在链接器看来,当它通过 *.o 或者配合 *.so 文件来生成可执行文件时,它对 ELF 格式的文件以链接视图 (Linking View) 进行看待。也就是说链接器以 Section 的形式来对待和处理 ELF 文件,诸如我们常见说的代码段 (.text) 、数据段 (.data .bss) 等待概念。当程序最终需要被装载成进程时,装载器就出场了,装载器将可执行文件以装载视图 (Executive View) 进行看待。装载器将以 Segment 的形式来处理 ELF 文件。网上很多教程也是这样说的,大家可能还是理解的不是很明白,后面我们通过实例的方式将进一步向大家来澄清这两者的区别。

   既然
*.o *.so 和可执行文件都是 ELF 格式,那么链接器和装载器是如何区分它们的呢?
   看一个简单的例子:


    readelf –h 命令能够可以查看一个 EFL 文件的头部信息。因为 viewobj.o 是编译时的中间临时文件,所以它的“ Start of pgrogram headers ”和“ Number of program headers ”都为 0 ,说明他不是一个可执行文件。取而代之的是它有 9 section ,所以它有“ Start of section headers ”和“ Number of section headers ”都有数据。
   
再看一下动态共享库:

    
   在
Linux下动态共享库被当作可执行文件来处理,虽然它不能单独执行,但某些应用程序的运行离不了它。
   
最后是可执行文件,这个就不用多说了,看图:

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值