当前位置:   article > 正文

为何.bss段不占用磁盘资源

为何.bss段不占用磁盘资源

elf文件中.bss段:存放未初始化的全局变量,将.data和.bss分开的理由是为了节约磁盘空间,.bss不占实际的磁盘空间。

这句话该怎么理解呢?

我们先创建一个main.c文件,如下所示。

#include <stdio.h>
int a[1000];
int b[1000] = {1};
int main()
{
printf("Hello!");
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在linux环境下用gcc main.c -o a.out编译一下,得到可执行文件a.out。
使用ls -l a.out命令和size a.out查看a.out的段的大小以及占用的磁盘空间。
在这里插入图片描述
可见此时可执行文件a.out所占用的磁盘内存空间为12368个字节,而.bss段显示的大小为4032个字节。
接下来将刚才的main.c文件修改一下,为全局变量附上初值。

#include <stdio.h>
int a[1000] = {1};
int b[1000] = {1};
int main()
{
printf("Hello!");
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

利用gcc编译再次生成可执行文件,并查看其占用的磁盘空间以及各段显示的大小。
在这里插入图片描述
可以看到可执行文件的大小增加了4000个字节,也正好是我们刚才初始化后的a[1000]的大小,并且时在.data段增加了4000个字节,因此印证了将未初始化的全局变量储存在.bss段是不会消耗磁盘空间的说法。
当程序加载到内存运行时,就会为.bss段中的数据分配内存并且进行初始化了。

那么程序是如何知道该为我们未初始化的全局变量分配多大的空间的呢?

使用readelf -S a.out查看可执行文件的段表,段表记录了每个段的名称、类型、地址、偏移、大小等信息。通过这个表中记录的.bss段的信息,系统就会知道加载程序去运行时,应该给我们存放在.bss段里的变量分配多大的内存了。下图为未初始化数组a时,.data和.bss的段信息,可以看到他们的size都是0xfc0 = 4032(dec)
在这里插入图片描述
当我们将a数组进行初始化之后,将会发生以下变化,即将已经初始化后的数组a放进了.data段,即0xfc0+4000(dec) = 0x1f60
在这里插入图片描述
此外,在elf文件结构中,有一个字符串表.strtab,里面存放的是elf文件中各个段的名字以及变量名等字符串,字符串表中记录了这些字符串以及对应的下标,需要用到这些字符串时,直接用偏移下标去取就行了。段表中存放的段的名字这一项,就是存的.strtab中对应字符串的偏移。

通过readelf -s a.out 查看可执行文件的符号表,以47行的b为例,4000代表的是其大小,OBJECT表示其是个变量等。
在这里插入图片描述
(.strtab和.systab还不是很理解,后面再补!)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/319477
推荐阅读
相关标签
  

闽ICP备14008679号