所有初始化的全局/静态变量都将转到初始化数据部分。 所有未初始化的全局/静态变量将转到 uninitialed data section (BSS)。 BSS中的变量在程序加载时间内将得到一个值。
如果全局变量显式初始化为零(int myglobal = 0
),那么该变量将被存储在哪里?
答案 0 :(得分:29)
编译器可以将此类变量自由放入bss
以及data
。例如,GCC有special option控制此类行为:
-fno-zero-initialized-in-bss
如果目标支持BSS部分,则GCC默认将初始化为零的变量放入BSS。这个 可以节省生成代码中的空间。此选项会关闭此选项 行为,因为一些程序明确依赖变量 数据部分。例如,以便生成的可执行文件可以找到 该部分的开头和/或基于此做出假设。
默认值为
-fzero-initialized-in-bss
。
尝试使用以下示例(test.c
文件):
int put_me_somewhere = 0;
int main(int argc, char* argv[]) { return 0; }
没有选项进行编译(隐式-fzero-initialized-in-bss
):
$ touch test.c && make test && objdump -x test | grep put_me_somewhere
cc test.c -o test
0000000000601028 g O .bss 0000000000000004 put_me_somewhere
使用-fno-zero-initialized-in-bss
选项进行编译:
$ touch test.c && make test CFLAGS=-fno-zero-initialized-in-bss && objdump -x test | grep put_me_somewhere
cc -fno-zero-initialized-in-bss test.c -o test
0000000000601018 g O .data 0000000000000004 put_me_somewhere
答案 1 :(得分:6)
测试特定的编译器很容易:
$ cat bss.c
int global_no_value;
int global_initialized = 0;
int main(int argc, char* argv[]) {
return 0;
}
$ make bss
cc bss.c -o bss
$ readelf -s bss | grep global_
32: 0000000000400420 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
40: 0000000000400570 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
55: 0000000000601028 4 OBJECT GLOBAL DEFAULT 25 global_initialized
60: 000000000060102c 4 OBJECT GLOBAL DEFAULT 25 global_no_value
我们正在寻找0000000000601028
和000000000060102c
的位置:
$ readelf -S bss
There are 30 section headers, starting at offset 0x1170:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[24] .data PROGBITS 0000000000601008 00001008
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 0000000000601018 00001018
0000000000000018 0000000000000000 WA 0 0 8
看起来这两个值都存储在我系统的.bss
部分:gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)
。
答案 2 :(得分:2)
行为取决于C实现。它可能最终以.data或.bss结尾,并且为了增加它不会最终的变化.data占用冗余空间,最好不要将它显式初始化为0,因为无论如何它都将被设置为0对象具有静态持续时间。