Lefteris Laskaridis
Lefteris Laskaridis

Reputation: 2322

Local and static variables in C (cont'd)

Building on my last question i'm trying to figure out how .local and .comm directives work exactly and in particular how they affect linkage and duration in C.

So I've run the following experiment:

static int value;

which produces the following assembly code (using gcc):

.local  value
.comm   value,4,4

When initialized to zero yields the same assembly code (using gcc):

.local  value
.comm   value,4,4

This sounds logical because in both cases i would expect that the variable will be stored in the bss segment. Moreover, after investigating using ld --verbose it looks that all .comm variables are indeed placed in the bss segment:

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   // ...
  }

When i initialize however my variable to a value other than zero, the compiler defines the variable in the data segment as i would expected, but produces the following output:

        .data
        .align 4
        .type   value, @object
        .size   value, 4
value:
        .long   1

Besides the different segments (bss and data respectively) which thanks to your help previously i now understand, my variable has been defined as .local and .comm in the first example but not in the second. Could anyone explain that difference between the two outputs produced from each case?

Upvotes: 2

Views: 821

Answers (2)

ecatmur
ecatmur

Reputation: 157484

The .local directive marks a symbol as a local, non-externally-visible symbol, and creates it if it doesn't already exist. It's necessary for 0-initialized local symbols, because .comm declares but does not define symbols. For the 1-initialized variant, the symbol itself (value:) declares the symbol.

Using .local and .comm is essentially a bit of a hack (or at least a shorthand); the alternative would be to place the symbol into .bss explicitly:

        .bss
        .align 4
        .type   value, @object
        .size   value, 4
value:
        .zero   4

Upvotes: 1

Dmytro Sirenko
Dmytro Sirenko

Reputation: 5083

Linux kernel zeros the virtual memory of a process after allocation due to security reasons. So, the compiler already knows that the memory will be filled with zeros and does an optimization: if some variable is initialized to 0, there's no need to keep space for it in a executable file (.data section actually takes some space in ELF executable, whereas .bss section stores only its length assuming that its initial contents will be zeros).

Upvotes: 1

Related Questions