我正在尝试学习C程序的可执行文件的结构.我的环境是GCC和64位Intel处理器.
请考虑以下C代码a.cc
.
#include <cstdlib>
#include <cstdio>
int x;
int main(){
printf("%d\n", sizeof(x));
return 10;
}
Run Code Online (Sandbox Code Playgroud)
该size -o a
节目
text data bss dec hex filename
1134 552 8 1694 69e a
Run Code Online (Sandbox Code Playgroud)
我添加了另一个初始化的全局变量y.
int y=10;
Run Code Online (Sandbox Code Playgroud)
该size a
节目(其中a
从a.cc可执行文件的名称)
text data bss dec hex filename
1134 556 12 1702 6a6 a
Run Code Online (Sandbox Code Playgroud)
我们知道,该BSS
部分存储未初始化的全局变量的大小并DATA
存储已初始化的变量.
int
在BSS中占用8个字节?将sizeof(x)
在我的代码表明,int
实际占用了4个字节.int y=10
添加4个字节数据,是有道理的,因为int
应该采取4个字节.但是,为什么它会为BSS增加4个字节?size
删除两行后,两个命令之间的差异保持不变#include ...
.
更新:
我认为我对BSS的理解是错误的.它可能不存储未初始化的全局变量.正如维基百科所说:"BSS在运行时需要的大小记录在目标文件中,但BSS(与数据段不同)不会占用目标文件中的任何实际空间." 例如,即使是一行C代码int main(){}
也有bss 8
.
BSS的8或16是否来自alignment
?
它没有,它占用4个字节而不管它在哪个段.你可以使用nm
带有-S
参数的工具(来自GNU binutils包)来获取目标文件中所有符号的名称和大小.您可能会看到编译器的次要影响,包括或不包括某些其他符号,无论出于何种原因.
例如:
$ 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
Run Code Online (Sandbox Code Playgroud)
一个目标文件具有x
在未初始化数据段(C
)中命名的4字节对象,而另一个目标文件具有x
在初始化数据段(D
)中命名的4字节对象.