如果全局变量初始化为0,它会转到BSS吗?

时间:2012-01-04 02:52:26

标签: c gcc

所有初始化的全局/静态变量都将转到初始化数据部分。 所有未初始化的全局/静态变量将转到 uninitialed data section (BSS)。 BSS中的变量在程序加载时间内将得到一个值。

如果全局变量显式初始化为零(int myglobal = 0),那么该变量将被存储在哪里?

3 个答案:

答案 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

我们正在寻找0000000000601028000000000060102c的位置:

$ 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对象具有静态持续时间。