32

From my book:

.bss:

Uninitialized global C variables

COMMON:

Uninitalized data objects that are not yet allocated

I have to say, I don't quite see a clear distinction. I don't even quite understand what an uninitizalied, non-allocated data object is...seems like nothing. I've used GNU's readelf tool to try to take a look at some simple C code, but can't find a single COMMON symbol. I've read things like FORTRAN's COMMON type is an example of a COMMON symbol - but I don't know FORTRAN

Can someone possibly distinguish the two for me? If at all possible, hopefully with a C example? Greatly appreciated.

edit: from this post, the variable c here:

int c;
int main() {} ...

should be COMMON. But using objdump -t shows for me that c is in .bss...

confused

Community
  • 1
  • 1
gone
  • 2,587
  • 6
  • 25
  • 32

4 Answers4

31
// file a.c
// file-scope

int a = 0;  // goes into BSS

after compilation of a.c into object file a.o, a symbol goes into BSS section.

// file b.c
// file-scope

int b;  // goes into COMMON section

after compilation of b.c into object file b.o, b symbol goes into COMMON section.

After linking of a.o and b.o, both a and b symbols goes into BSS section. Common symbols only exist in object files, not in executable files. The idea of COMMON symbols in Unix is to allow multiple external definitions of a same variable (in different compilation units) under a single common symbol under certain conditions.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Ah this makes perfect sense now! Marking this as correct since it's just a little more compact than Art's answer – gone May 30 '13 at 12:36
  • 6
    `int a = 0;` doesn't necessarily go into .bss. It's actually a recent change to gcc. Initializing something to 0 used to force the symbol into data on older gcc versions and was often used when you needed an possibility to edit the binary while keeping the initialized variable at 0. Most often (ab)used by kernels. Also notice that commons don't necessarily have to go into bss, it's possible to have a bunch of commons resolve into a symbol in the data section. – Art May 30 '13 at 12:42
  • Is this specific to Unix or the .elf format? I'm used to .elf but not to Unix, and I have never heard about "COMMON" before. – Lundin May 30 '13 at 12:57
  • @Lundin I think it originally came from Unix and was later reused in ELF format. – ouah May 30 '13 at 13:21
  • Also this is one of the areas where C++ differs. At least gcc will behave as if -fno-common was specified for C++ code. – textshell Feb 28 '16 at 21:47
  • Why is `a = 0` considered uninitialized global data? What is considered initialized to go into the .data section? – mashrur May 17 '19 at 14:36
16

Commons only appear before the linking stage. Commons are what later goes into the bss or data‚ but it's up to the linker to decide where it goes. This allows you to have the same variable defined in different compilation units. As far as I know this is mostly to allow some ancient header files that had int foo; in them instead of extern int foo;.

Here's how it works:

$ cat > a.c
int foo;
$ cat > b.c
int foo;
$ cat > main.c
extern int foo;
int main(int argc, char **argv) { return foo; }
$ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o
$ objdump -t a.o | grep foo
0000000000000004       O *COM*  0000000000000004 foo
$ objdump -t b.o | grep foo
0000000000000004       O *COM*  0000000000000004 foo
$ objdump -t x | grep foo
0000000000600828 g     O .bss   0000000000000004              foo
$

Notice that this only works when at most one of the variables in the different compilation units is initialized.

$ echo "int foo = 0;" > a.c
$ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o
$ echo "int foo = 0;" > b.c
$ cc -c a.c && cc -c b.c && cc -c main.c && cc -o x a.o b.o main.o
b.o:(.bss+0x0): multiple definition of `foo'
a.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
$

This is scary stuff, compatibility with ancient systems and you should never rely on it. Do things properly - only one definition of global variables in all compilation units, declare it extern it everywhere else through a header.

Art
  • 19,807
  • 1
  • 34
  • 60
  • There is no this `COMMON` section when I use `readelf -S a.o`, why? (with `int a;` in a.c) – Elinx Sep 20 '16 at 07:52
  • 3
    @elinx Commons are not a section but rather specially marked symbols that are put in the right sections at the linking stage. `readelf -S` dumps the sections. Commons will show up when you dump the symbols with `readelf -s`. – Art Sep 20 '16 at 08:10
9

If you allow common during linking different units can declare the same variable and the the linker will locate them at the same location. The types don't even need to be the same, so it is some kind of link time union. This is the COMMON feature from Fortran. If you don't allow common in linking C then, such a situation will result in a link time error. Such common linking is only possible for uninitialized globals, because otherwise it is unclear which initialization should be taken.

The globals going to bss are just uninitialized globals that C defines as being initialized to 0. Most object formats support sections where only the size is given and the loader will fill the whole section with zeros.

P.S: If you use gcc you can use the -fno-common option to force common symbols to the bss section, which as Art argues is good and advisable practice.

Bryan Olivier
  • 5,207
  • 2
  • 16
  • 18
-1

static variables end up in the .bss section.Un-initialised global variables (not static) goes in .common section.

static a;  //bss
int c;   //.common
main(){
}
Dayal rai
  • 6,548
  • 22
  • 29