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

Lun*_*oms 25 c gcc

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

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

Eld*_*mov 33

编译器可以自由地将这样的变量bss放入data.例如,GCC有一个控制此类行为的特殊选项:

-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; }
Run Code Online (Sandbox Code Playgroud)

没有选项编译(隐式-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
Run Code Online (Sandbox Code Playgroud)

使用-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
Run Code Online (Sandbox Code Playgroud)


sar*_*old 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
Run Code Online (Sandbox Code Playgroud)

我们正在寻找的位置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
Run Code Online (Sandbox Code Playgroud)

看起来这两个值都存储在.bss我系统的部分中:gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4).