作为一名Linux小白,第一次看到a.out这个名字,感觉实在是奇怪,搜了一下才知道这是编译器输出的默认可执行文件名

然后vi一下,哇,各种乱码,仔细看看,发现了三个清晰的字符ELF。继续搜索, 第一感觉就是这就是windows下的*.exe

顺便看到了readelf这条命令,就读了一下这个文件,发现这里边好多东西都不懂,后来在学习linux的过程中渐渐明白了

一部分,前几天刚好跟同学说到了关于ELF文件数据布局的问题,今天总结一下(罗嗦了这么多,真是不好意思)。


今天讨论的问题是:我们在源程序中定义的变量是否会被存储在ELF中以及存放在什么地方。让我们一步一步往下看:

先抛出两个结论:

a. data段的数据存储在ELF文件中;

b. bss段的数据不存储在ELF文件中,ELF文件中的bss段只是记录bss段所需要的大小。

1. 对比代码, 下面这段代码用于对比测试:

 int main( ) {
return ;
}

测试结果:

du -h a.out
.0K a.out size a.out
   text       data        bss        dec        hex    filename
   1056        252          8       1316        524    a.out

2. 全局变量

2.1 未初始化:

 int a[];
int main( ) {
return ;
}

测试结果:

du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
153c a.out

可以看出,bss段的值变为了4128,正好是32 + 4096,为什么不是8 + 4096,我想应该是bss段是32字节对齐的,至于初始为什么没有对齐,留待大神解释。

那么为什么a.out的大小还是8.0K呢?大家先想一想。

2.2 初始化

 int a[] = {  };
int main( ) {
return ;
}

可能有同学要说了,你这只初始化了一个值吗?先往下看:

测试结果:

du -h a.out
12K a.out
size a.out
text data bss dec hex filename
153c a.out

这次bss段值没变,而数据段多了4372 - 252 = 4120,为什么不是4096,说明data段应该也是32字节对齐的。细心的同学肯定发现了,a.out的大小增加

了4K,这说明什么,说明a[1024]数据被写入了ELF文件中,也就是说data段中变量的值全部被写入到了ELF文件中。那现在想一想,为什么bss段增加了而a.out

没有增加呢,说明bss段只是记录了变量占据存储空间的大小,并没有在ELF中为变量分配存储,这里可以证明上面的两个结论是正确的。

现在回答一下上面的问题,为什么我只初始化了一个值,其实我们知道,数组是连续存放的,因此,只要初始化了一个值,其它的数据地址也就确定了。

3. 静态变量

3.1 未初始化

 int main( ) {
static int a[];
return ;
}

测试结果:

du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
153c a.out

bss段增加了4096 + 对齐字节,说明未经初始化的静态变量在bss段。

3.2 初始化

 int main( ) {
static int a[] = { };
return ;
}

测试结果:

du -h a.out
12K a.out
size a.out
text data bss dec hex filename
153c a.out

data段增加了4096 + 对齐字节,目标文件a.out增加了4K,说明经过初始化的静态变量在data段。

4. 字符串常量

 int main( ) {
char *p = "";
return ;
}

测试结果:

du -h a.out
7122    a.out
size a.out
text data bss dec hex filename
a.out
1 int main( ) {
char *p = "";
return ;
}

测试结果:

du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
a.out

可以看到只有text段增加了,而且通过设置不同的长度,第二次比第一增加了10B,说明“确实”是被放在text段了。但经过进一步分析,使用readelf命令,发现实际上

"666666666666"的地址在rodata段范围内,实际上字符串常量是被存储在rodata段中的,size命令看来也是个坑啊!需要指出,rodata段的内容也是要占据ELF文件

存储的,并不仅仅只记录数据大小。

5. 局部变量

这些变量不会存储在ELF中,只有装载ELF时,才会在内存中分配,下一篇文章我会讨论这个问题。

下表是我在Linux内核版本3.2.0的测试结果:

变量属性 是否在ELF中 是否存储在ELF中
未经初始化的全局变量 bss段
经过初始化的全局变量 data段
未经初始化的静态变量 bss段
经过初始化的静态变量 data段
字符串常量 rodata段
宏定义常量 rodata段
局部变量  

由于本人水平有限,文章中不当和错误之处不可避免,欢迎大家批评指正,愿共同进步!!!

最新文章

  1. 俄罗斯画师Mikhail Rakhmatullin作品
  2. 【干货】如何通过OPC自定义接口来实现客户端数据的读取?
  3. androidTV第一次创建(转:支持原创)
  4. webStorm破解说明
  5. 2016年11月27日 星期日 --出埃及记 Exodus 20:18
  6. ToString()使用方法
  7. 2016GIAC全球互联网架构大会日程分享
  8. Cookie中文乱码问题
  9. JavaScript OOP(三):prototype原型对象(即构造函数的prototype属性)
  10. CentOS7上安装Nginx、PHP、MySQL
  11. springmvc 学习
  12. SharePoint 2013: Workflow Manager Backend 服务意外地终止
  13. Javascript 对象复制
  14. /usr/bin/ld: 找不到 -lmsc----解决方案
  15. EOS开发基础之二:使用cleos命令行客户端操作EOS(钱包wallet基础操作)
  16. Python3.x文件处理详解
  17. 1-vim的复制粘贴
  18. Nginx的Rewrite正则表达式,匹配非某单词
  19. Swift AVFoundation 二维码扫描和生成
  20. Spark的CombineByKey

热门文章

  1. Socket编程指南及示例程序
  2. 如何注册Uber司机,加入uber(全国版最新最详细注册流程)
  3. Linux特殊权限:SUID、SGID、SBIT
  4. <td style="word-break:break-all"> 在html中控制自动换行
  5. poj 1961 Period(KMP训练指南例题)
  6. VS2015自定义注释内容
  7. iOS面试题04-runtime
  8. ASP.NET之电子商务系统开发-1(数据列表)
  9. 【iOS】Mapkit的使用:地图显示、定位、大头针、气泡等
  10. ajax 上传图片 并预览