【问题标题】:Why the int type takes up 8 bytes in BSS section but 4 bytes in DATA section为什么 int 类型在 BSS 部分占 8 个字节,而在 DATA 部分占 4 个字节
【发布时间】:2014-07-18 20:37:21
【问题描述】:

我正在尝试学习 C 程序的可执行文件的结构。我的环境是 GCC 和 64 位 Intel 处理器。

考虑以下 C 代码a.cc

#include <cstdlib>
#include <cstdio>

int x;

int main(){
  printf("%d\n", sizeof(x));
  return 10;
}

size -o a 节目

 text      data     bss     dec     hex filename
 1134       552       8    1694     69e a

在我添加另一个初始化的全局变量 y 之后。

int y=10; 

size a 显示(其中a 是来自 a.cc 的可执行文件的名称)

 text      data     bss     dec     hex filename
 1134       556      12    1702     6a6 a

众所周知,BSS 部分存储未初始化的全局变量的大小,DATA 存储已初始化的变量。

  1. 为什么int在BSS中占用8个字节?我代码中的sizeof(x) 表明int 实际上占用了4 个字节。
  2. int y=10 为 DATA 添加了 4 个字节,这是有道理的,因为 int 应该占用 4 个字节。但是,为什么要给 BSS 增加 4 个字节呢?

删除#include ... 这两行后,两个size 命令之间的差异保持不变。

更新: 我认为我对 BSS 的理解是错误的。它可能不存储未初始化的全局变量。正如维基百科所说,“BSS 在运行时需要的大小记录在目标文件中,但 BSS(与数据段不同)不占用目标文件中的任何实际空间。”例如,即使是一行 C 代码int main(){} 也有bss 8

BSS的8位还是16位来自alignment

【问题讨论】:

  • 你看过汇编代码吗?它可以在 bss 中声明并稍后使用
  • @JoachimPileborg 我在 Wikipedia 中看到了这一点,这让我对 BSS 部分感到困惑。谢谢。
  • 没有全局变量时bss为0?
  • 你说的是C还是C++?您始终提到 C,但您的示例程序是 C++。如果你删除变量x,你会得到什么 BSS 大小?
  • 此代码不是有效的 C,size -o 不可能打印 8,因为 -o 表示“八进制”。投票结束,因为不可复制。

标签: c linux gcc


【解决方案1】:

它不会,无论它在哪个段中,它都占用 4 个字节。您可以使用 nm 工具(来自 GNU binutils 包)和 -S 参数来获取所有的名称和大小目标文件中的符号。您可能会看到编译器的次要影响,无论出于何种原因,包括或不包括某些其他符号。

例如:

$ cat a1.c
int x;
$ cat a2.c
int x = 1;
$ gcc -c a1.c a2.c
$ nm -S a1.o a2.o

a1.o:
0000000000000004 0000000000000004 C x

a2.o:
0000000000000000 0000000000000004 D x

一个对象文件在未初始化数据段(C)中有一个名为x的4字节对象,而另一个对象文件在初始化数据段(@987654327)中有一个名为x的4字节对象@)。

【讨论】:

  • +1 运行时库中链接的启动代码很可能会占用size 看到的额外空间(如果我不得不猜测(总是危险的) ,我会说它类似于 errno 或其他少数商品中的任何一种;例如,mach-o 图像包括用于 dynalib 加载程序的存根绑定器)。
  • 谢谢。我想更多地了解可执行文件的结构。比如,BSS 到底做了什么?
  • @PengZhang:BSS段通常是一个有地址和大小的段(因此可以映射到内存)但不包含实际的初始化数据(因此没有什么可以存储到文件中)。加载后可作为可读写内存使用;就像普通的 DATA 一样。
  • @Jongware 谢谢。那么当 DATA 和 TEXT 将被复制到内存中时,BSS 不会? BSS 是否作为对 OS 的通知,以便 linux 在加载程序时知道如何分配程序所需的内存(除了 TEXT 和 DATA)?
  • @PengZhang:听起来很对。找到适合您平台的可执行格式的良好描述,并找到一个工具(或编写一个!)来转储原始数据。您将看到没有与 BSS 段关联的文件数据。
猜你喜欢
  • 2015-11-30
  • 2015-09-29
  • 1970-01-01
  • 2022-07-06
  • 2019-08-12
  • 1970-01-01
  • 2018-07-05
  • 2018-05-12
  • 2020-07-24
相关资源
最近更新 更多