我正在尝试学习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
存储已初始化的变量。
int
在BSS中占用8个字节?我的代码中的sizeof(x)
显示int
实际上占用了4个字节。 int y=10
向DATA添加了4个字节,这是有意义的,因为int
应该占用4个字节。但是,为什么它会向BSS添加4个字节? 删除两行size
后,两个#include ...
命令之间的差异保持不变。
更新
我认为我对BSS的理解是错误的。它可能不存储未初始化的全局变量。正如维基百科所说&#34; BSS在运行时需要的大小记录在目标文件中,但BSS(与数据段不同)并不占用目标文件中的任何实际空间。&#34;例如,即使是一行C代码int main(){}
也有bss 8
。
BSS的8或16是来自alignment
吗?
答案 0 :(得分:9)
它不会占用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
一个目标文件在未初始化的数据段(x
)中有一个名为C
的4字节对象,而另一个目标文件在其中有一个名为x
的4字节对象初始化数据段(D
)。