为什么在添加变量时,.bss段没有增加?

7
最近,我了解到.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

尝试添加 int big[1024] 或类似的内容。BSS 可能具有基本大小,仅包含三个变量而不会改变。 - Paul Ogilvie
1
可能的重复:https://dev59.com/Al0Z5IYBdhLWcg3wphsE请注意,这是一个自动翻译,如有需要,请参考原始英文文本。 - Achal
3
可能是UNIX中的SIZE命令的重复问题。 - iBug
该命令显示大小,而不会修改大小。我理解这可能不是您的本意,但那是您所写的。在自然语言和代码中,语义非常重要。我更改了标题以使问题在语义上正确,并且与BSS和编译器有关,而不是与大小命令有关。 - Clifford
1个回答

5
这是因为全局变量的工作方式。
解决的问题是在多个.c文件中声明一个未初始化的全局变量而不会出现重复符号错误。也就是说,每个全局未初始化声明都像一个弱声明一样工作,如果没有其他声明包含初始化,则可以将其视为外部声明。
编译器是如何实现这一点的?很容易:
- 在编译时,它将把该变量添加到COMMON段中,而不是添加到BSS段中。 - 然后,在链接时,它将合并所有具有相同名称的COMMON变量,并且丢弃已经存在于其他部分的任何变量。剩下的变量将被移动到可执行文件的BSS段中。
这就是为什么你看不到对象文件的BSS节中的变量,但可以在可执行文件中看到的原因。
您可以使用比size更现代的替代方法(例如objdump -x)检查对象节的内容。请注意变量是如何放置在*COM*中的。
值得注意的是,如果将全局变量声明为静态的,则表示该变量属于该编译单元,因此不使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接