C 为什么int类型在BSS部分占用8字节,而在数据部分占用4字节
我试图学习C程序可执行文件的结构。我的环境是GCC和64位Intel处理器 考虑以下C代码C 为什么int类型在BSS部分占用8字节,而在数据部分占用4字节,c,linux,gcc,C,Linux,Gcc,我试图学习C程序可执行文件的结构。我的环境是GCC和64位Intel处理器 考虑以下C代码a.cc #include <cstdlib> #include <cstdio> int x; int main(){ printf("%d\n", sizeof(x)); return 10; } 在我添加了另一个初始化的全局变量y之后 int y=10; 显示大小a(其中a是a.cc中可执行文件的名称) 我们知道,BSS部分存储未初始化全局变量的大小,DATA
a.cc
#include <cstdlib>
#include <cstdio>
int x;
int main(){
printf("%d\n", sizeof(x));
return 10;
}
在我添加了另一个初始化的全局变量y之后
int y=10;
显示大小a
(其中a
是a.cc中可执行文件的名称)
我们知道,BSS
部分存储未初始化全局变量的大小,DATA
存储初始化的全局变量
int
在BSS中占用8个字节?我的代码中的sizeof(x)
表明int
实际上占用了4个字节。int
应该需要4个字节,因此int y=10
向数据添加了4个字节,这是有意义的。但是,为什么它会向BSS添加4个字节?#include…
后,两个size
命令之间的差异保持不变
更新:
我认为我对BSS的理解是错误的。它可能不会存储未初始化的全局变量。正如维基百科所说,“BSS在运行时需要的大小记录在对象文件中,但BSS(与数据段不同)不会占用对象文件中的任何实际空间。”例如,即使是一行C代码int main(){}
也有BSS 8
BSS的8或16是否来自
对齐
?不是,它占用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字节对象,而另一个对象文件在初始化数据段(D
)中有一个名为x
的4字节对象。您看过汇编代码了吗?它可以在bss中声明并使用later@JoachimPileborg我在维基百科上看到了这一点,这让我对BSS部分感到困惑。谢谢。当没有全局变量时,<代码> BSS 是0?你是在谈论C还是C++?您遍及C,但您的示例程序是C++。如果删除变量x
,您得到的BSS大小是多少?此代码不是有效的C,并且size-o
可能无法打印8,因为-o
表示“八进制”。投票以不可复制的方式关闭。+1运行库中链接的启动代码很可能会占用size
显示的额外空间(如果我不得不猜测的话(总是危险的),我会说它是类似于errno
或其他一些商品的东西;例如,mach-o图像包括dynalib loader的存根活页夹)。谢谢。我想更多地了解可执行文件的结构。例如,BSS到底是做什么的?@penzhang:BSS段通常是一个有地址和大小的段(因此可以映射到内存),但不包含实际的初始化数据(因此没有存储到文件中的内容)。加载后,可作为可读写存储器使用;就像普通数据一样。@Jongware谢谢。因此,虽然数据和文本将被复制到内存中,但BSS不会?BSS是否可以作为一个通知给操作系统,让linux知道在加载程序时如何分配程序所需的内存(除了文本和数据)?@penzhang:听起来不错。找到平台可执行文件格式的良好描述,并找到一个工具(或编写工具!)来转储原始数据。您将看到没有与BSS段关联的文件数据。
text data bss dec hex filename
1134 556 12 1702 6a6 a
$ 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