为什么添加变量时.bss段不会增加?

时间:2017-12-09 10:30:44

标签: c linux

最近,我了解到.bss段存储了未初始化的数据。但是,当我尝试如下的小程序并在终端中使用size(1)命令时,即使添加了一些全局变量,.bss段也没有改变。我误解了什么吗?

jameschu@aspire-e5-573g:~$ cat test.c
#include <stdio.h>

int main(void)
    {
  printf("hello world\n");
  return 0;
}
jameschu@aspire-e5-573g:~$ gcc -c test.c 
jameschu@aspire-e5-573g:~$ size test.o
   text    data     bss     dec     hex filename
     89       0       0      89      59 test.o
jameschu@aspire-e5-573g:~$ cat test.c
#include <stdio.h>
int a1;
int a2;
int a3;

int main(void)
{
  printf("hello world\n");
  return 0;
}
jameschu@aspire-e5-573g:~$ gcc -c test.c 
jameschu@aspire-e5-573g:~$ size test.o
   text    data     bss     dec     hex filename
     89       0       0      89      59 test.o

1 个答案:

答案 0 :(得分:3)

这是因为全局变量的工作方式。

正在解决的问题是,可以在几个.c文件中声明一个全局变量而不初始化,并且不会出现重复的符号错误。也就是说,每个全局未初始化的声明都像 weak 声明一样工作,如果没有其他声明包含初始化,则可以将其视为external

编译器如何实现?易:

  • 编译时,不会在bss段中添加该变量,而是将其添加到COMMON段。
  • 但是,在链接时,它会合并所有具有相同名称的COMMON变量,并丢弃已在其他部分中的任何人。其余的将移至可执行文件的bss

这就是为什么你在目标文件的bss中看不到你的变量,但你在可执行文件中看到了。

您可以使用size的更现代的替代方法检查对象部分的内容,例如objdump -x。并注意变量如何放在*COM*

值得注意的是,如果将全局变量声明为static,则表示该变量属于该编译单元,因此未使用COMMON并获得您期望的行为:

int a;
int b;
static int c;

$ size test.o
text       data     bss     dec     hex filename
 91       0       4      95      5f test.o

初始化为0会得到类似的结果。

int a;
int b;
int c = 0;

$ size test.o
text      data    bss    dec     hex    filename
 91       0       4      95      5f test.o

但是,初始化为0以外的任何内容都会将该变量移至data

int a;
int b = 1;
int c = 0;

$ size test.o
text      data    bss    dec     hex    filename
 91       4       4      99      5f test.o