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:
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.
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 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.
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.
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
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.
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