.bss vs COMMON: what goes where?

前端 未结 4 2238
离开以前
离开以前 2020-12-03 17:10

From my book:

.bss:

Uninitialized global C variables

COMMON:

Uninitalized data objects that are n

4条回答
  •  醉酒成梦
    2020-12-03 17:19

    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.

提交回复
热议问题