Endy
Endy

Reputation: 115

Why don't I get static variables in the BSS?

To the best of my understanding, static variables that are not explicitely initialized (and, with GCC, even those that are explicitely initialized to zero if -fzero-initialized-in-bss is set, which is the case by default) are usually stored in the BSS segment. Yet, it seems that when I try to inspect that behaviour, those variables are stored in the general data section (with initialized globals). If I compile (with -O0 for good measure) and run:

#include <stdio.h>
#include <stdlib.h>

extern char etext, edata, end;

int i = 42;

int main(int argc, char* argv[])
{
        static int j;
        printf ("end of program (etext) = %10p\n",&etext);
        printf ("end of initialized data (edata) = %10p\n",&end);
        printf ("end of uninitialized data (end) = %10p\n",&end);
        printf ("=====\n");
        printf ("Value of i (initialized global) : %d\n",i);
        printf ("Address of i : %10p\n",&i);
        printf ("Value of j (static with no explicit initialization) : %d\n",j);
        printf ("Address of i : %10p\n",&j);
        return 0;
}

I get the output:

end of program (etext) =   0x40067d
end of initialized data (edata) =   0x600af0
end of uninitialized data (end) =   0x600af0
=====
Value of i (initialized global) : 42
Address of i :   0x600ae0
Value of j (static with no explicit initialization) : 0
Address of i :   0x600ae8

So i and j are stored at contiguous memory address, between &etext and &edata, which is the regular data section. Furthermore, it seems that &edata == &end which, if I understand correctly, would mean that the BSS is empty.

Now I realize that where the compiler puts which variable is an implementation choice and the results it produces is correct. But I am just wondering why I get that behaviour, and if there is a way to tell gcc to explicitely put such variables in the BSS (I didn't see any obvious solution in the manual).

Upvotes: 3

Views: 823

Answers (2)

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

The BSS in the executable image is just a number that says how many bytes to reserve upon load for the uninitialized variables. In this way the image doesn't get unwieldly large for many of these uninitialized variables. When the number is very small, such as in your example, there is hardly any saving and only overhead and the compiler may have decided to place them all in the DATA segment.

Upvotes: 3

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31193

You have an error in your code. You print the address of end for both edata and end, so of course you assume edata == end, which they are not.

When I fixed your code and run it I get:

end of program (etext) = 0x8048578
end of initialized data (edata) = 0x804988c
end of uninitialized data (end) = 0x8049894

Value of i (initialized global) : 42
Address of i : 0x8049888
Value of j (static with no explicit initialization) : 0
Address of j : 0x8049890

So clearly j is in the area between edata and end and not in the same place as i.

(gcc 5.2.1 20150911 (Debian 5.2.1-17), 32bit)

Upvotes: 4

Related Questions