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

Jam*_*Chu 5 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
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 5

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

正在解决的问题是,可以在多个文件中声明全局变量而不对其进行初始化.c,并且不会出现重复符号错误。也就是说,每个全局未初始化声明的工作方式都类似于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
Run Code Online (Sandbox Code Playgroud)

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

int a;
int b;
int c = 0;

$ size test.o
text      data    bss    dec     hex    filename
 91       0       4      95      5f test.o
Run Code Online (Sandbox Code Playgroud)

但是,初始化为除此以外的任何值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
Run Code Online (Sandbox Code Playgroud)