bss段不占据磁盘空间的理解

elf文件中.bss段:
存放未初始化的全局变量,将.data和.bss分开的理由是为了节约磁盘空间,.bss不占实际的磁盘空间。这句话该怎么理解呢?
可以看下面的例子:

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

这里编写了一个test.c的文件,gcc编译gcc test.c -o test之后,使用ls -l test命令可以得到可执行文件的信息,我们只关注文件的大小为12608。
这里写图片描述
使用命令size test查看各个段的大小(不包含stack和heap段):
这里写图片描述
接着我们修改源程序:

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

编译之后,使用ls -l test命令再次查看可执行文件的信息
这里写图片描述
使用命令size test查看段的大小
这里写图片描述
可以看到大小从12608变成了16608,与之前相对比,该文件占据的大小涨了4000字节,这不就是我们的数组a[1000]的大小吗?我们所在的改动仅仅是初始化了a[1000],让这个数组的所在段从.bss段改到了.data段。通过size test命令查看bss段的大小也减小了。这就证明了.bss段中的数据并没有占据磁盘空间,从而节约了磁盘的空间。

当程序加载运行时,就会为.bss段中的数据分配内存已经进行初始化了。
下面还有两个疑问,那就是int a[1000]既然不占据实际的磁盘空间(是指不占据应该分配的内存大小),那么它的大小和符号存在哪呢?
.bss段占据的大小存放在ELF文件格式中的段表(Section Table)中,段表存放了各个段的各种信息,比如段的名字、段的类型、段在elf文件中的偏移、段的大小等信息。
我们可以通过命令readelf -S test来查看test可执行文件的段表(这里只截取了一部分):
这里写图片描述

这里再额外说明一个很有趣的地方,在elf文件结构中,有一个字符串表.strtab,里面存放的是elf文件中各个段的名字以及变量名等字符串,字符串表中记录了这些字符串以及对应的下标,需要用到这些字符串时,直接用偏移下标去取就行了。段表中存放的段的名字这一项,就是存的.strtab中对应字符串的偏移。

.bss段所占空间的大小存在哪里解决了,那么就剩下符号了。
符号当然对应的存在符号表.symtab中了。
我们可以通过命令readelf -s test来查看:
这里写图片描述
在第49行,我们看到了定义的全局数组b[1000]4000那一项表明数据的大小是4000字节,OBJECT代表是一个变量,GLOBAL代表是作用域是全局的。

最后我们总结一下:
.bss不占据实际的磁盘空间,只在段表中记录大小,在符号表中记录符号。当文件加载运行时,才分配空间以及初始化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值