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
In computer programming, the block starting symbol (abbreviated to . bss or bss) is the portion of an object file, executable, or assembly language code that contains statically allocated variables that are declared but have not been assigned a value yet. It is often referred to as the "bss section" or "bss segment".
Common Section means that part of the Fixed Link which is normally used by all categories of trains for the delivery of the services described in Article 1 of the Intergovernmental Commission Regulation of 25 October 2005 concerning the use of the Channel Tunnel by international groupings or railway undertakings.
The . bss section is used by the compiler for global and static variables. It is one of the default COFF sections that is used to reserve a specified amount of space in the memory map that can later be used for storing data. It is normally uninitialized.
bss section also includes *(COMMON) . This is a special input section where the compiler puts global uninitialized variables that go beyond file scope. int foo; goes there, while static int foo; does not. This allows the linker to merge multiple definitions into one symbol if they have the same name.
// 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With