Why has the .bss segment not increased when variables are added?
Asked Answered
S

1

7

Recently,I learned that the .bss segment stores uninitialized data. However, when I try a small program as below and use size(1) command in terminal, the .bss segment didn't change, even if I add some global variables. Do I misunderstand something?

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
Suspiration answered 9/12, 2017 at 10:30 Comment(4)
try adding int big[1024] or so. The bss may have a base size that doesn't change with only three variables.Anguilla
possible duplicates of https://mcmap.net/q/1098520/-size-command-in-unixLoveridge
Possible duplicate of SIZE command in UNIXStclair
The command shows the size it does not modify the size. I appreciate that is not what you meant, but that is what you wrote. Semantics is important in natural language as well as code. I changed the title so the question is semantically correct and about the BSS and the compiler and not about the size command.Voodooism
V
5

This is because the way global variables work.

The problem that is being solved is that it is possible to declare a global variable, without initializing it, in several .c files and not getting a duplicate symbol error. That is, every global uninitialized declaration works like a weak declaration, that can be considered external if no other declaration contains an initialization.

How it this implemented by the compiler? Easy:

  • when compiling, instead of adding that variable in the bss segment it will be added to the COMMON segment.
  • when linking, however, it will merge all the COMMON variables with the same name and discard anyone that is already in other section. The remaining ones will be moved to the bss of the executable.

And that is why you don't see your variables in the bss of the object file, but you do in the executable file.

You can check the contents of the object sections using a more modern alternative to size, such as objdump -x. And note how the variables are placed in *COM*.

It is worth noting that if you declare your global variable as static you are saying that the variable belongs to that compilation unit, so the COMMON is not used and you get the behavior you expect:

int a;
int b;
static int c;

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

Initializing to 0 will get a similar result.

int a;
int b;
int c = 0;

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

However initializing to anything other than 0 will move that variable to 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
Vitric answered 9/12, 2017 at 11:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.