所有初始化的全局/静态变量都将转到初始化数据部分。所有未初始化的全局/静态变量将转到未初始化的数据部分(BSS)。在程序加载期间,BSS中的变量将得到一个值0。
如果全局变量被显式初始化为零(int myglobal = 0
),那么该变量将存储在哪里?
发布于 2012-01-04 03:19:25
编译器可以自由地将这样的变量放入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
发布于 2012-01-04 03:01:24
很容易测试特定的编译器:
$ 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)
中。
发布于 2012-01-04 03:09:55
行为依赖于C实现。它可能在.data或.bss中结束,并且为了增加它最终不会在.data中占用冗余空间的更改,最好不要显式地将其初始化为0,因为如果对象具有静态持续时间,那么它将被设置为0。
https://stackoverflow.com/questions/8721475
复制相似问题