Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local and static variables in C

Tags:

c

static

assembly

When compiling this:

// external definitions
int value1 = 0;
static int value2 = 0;

the gcc compiler generates the following assembly:

.globl value1
        .bss
        .align 4
        .type   value1, @object
        .size   value1, 4
value1:
        .zero   4
        .local  value2
        .comm   value2,4,4

However, when i initialize the variables to a value other than zero such as:

// external definitions
int value1 = 1;
static int value2 = 1;

the gcc compiler generated the following:

.globl value1
        .data
        .align 4
        .type   value1, @object
        .size   value1, 4
value1:
        .long   1
        .align 4
        .type   value2, @object
        .size   value2, 4
value2:
        .long   1

My questions are:

  1. Why in the first case the values are allocated in the bss segment while in the second case in the data segment.
  2. Why value2 variable is defined as .local and .comm in the first case, while not in the second.
like image 709
Lefteris Laskaridis Avatar asked Nov 27 '12 09:11

Lefteris Laskaridis


People also ask

What is the difference between local and static variables?

Local variables are non existent in the memory after the function termination. However static variables remain allocated in the memory throughout the life of the program irrespective of whatever function.

What are local variables in C?

Local Variable: A local variable is a type of variable that we declare inside a block or a function, unlike the global variable. Thus, we also have to declare a local variable in c at the beginning of a given block. Example, void function1(){ int x=10; // a local variable.

What is static variables in C?

What is a Static Variable? In programming, a static variable is the one allocated “statically,” which means its lifetime is throughout the program run. It is declared with the 'static' keyword and persists its value across the function calls.

Are local variables static or dynamic in C?

The variable with a static keyword is declared inside a function is known as a static local variable. The scope of the static local variable will be the same as the automatic local variables, but its memory will be available throughout the program execution.


2 Answers

Generally speaking, the bss section contains uninitialized values and the data section contains initialized values. However, gcc places values that are initialized to zero into the bss section instead of the data section, as the bss section is zeroed out in runtime anyway, it doesn't make much sense to store zeros in the data section, this saves some disk space, from man gcc:

-fno-zero-initialized-in-bss If the target supports a BSS section, GCC by default puts variables that are initialized to zero into BSS. This can save space in the resulting code. This option turns off this behavior because some programs explicitly rely on variables going to the data section

I'm not sure why .comm is used with static storage which is local to an object file, it is usually used to declare common symbols that, if not defined/initialized, should be merged by the linker with symbol that have the same name from other object files and that's why it's not used in the second example because the variables are initialized, from the as manual

.comm declares a common symbol named symbol. When linking, a common symbol in one object file may be merged with a defined or common symbol of the same name in another object file

like image 156
iabdalkader Avatar answered Oct 13 '22 06:10

iabdalkader


The first case is because you initialized the values with zero. It's part of the C standard (section 6.7.8) that a global integer gets initialized with 0 if none is specified. So file formats made a provision to keep binaries smaller by having a special section these get placed in: bss. If you take a look at some of the ELF specification (on page I-15), you'll find this:

.bss This section holds uninitialized data that contribute to the program's memory image. By definition, the system initializes the data with zeros when the program begins to run. The section occupies no file space, as indicated by the section type, SHT_NOBITS.

In the first case, the compiler made an optimization. It doesn't need to take up room in the actual binary to store the initializer, since it can use the bss segment and get the one you want for free.

Now, the fact that you have a static coming in from an external source is a bit interesting (it's not typically done). In the module being compiled though, that should not be shared with other modules, and should be marked with .local. I suspect it does it this way because there is no actual value to be stored for the initializer.

In the second example, because you've given a non-zero initializer, it know resides in the initialized data segment data. value1 looks very similar, but for value2, the compiler needs to reserve space for the initializer. In this case, it doesn't need to be marked as .local because it can just lay down the value and be done with it. It's not global because there is no .globl statement for it.

BTW, http://refspecs.linuxbase.org/ is a good place to visit for some of the low-level details about binary formats and such.

like image 26
John Szakmeister Avatar answered Oct 13 '22 05:10

John Szakmeister