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

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

这句话该怎么理解呢?

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

#include <stdio.h>
int a[1000];
int b[1000] = {1};
int main()
{
printf("Hello!");
return 0;
}

在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;
}

利用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还不是很理解,后面再补!)

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值