3

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

1
  • Your code prints &end for both edata and end, is that a copy paste problem or the reason for this confusion? Commented Oct 16, 2015 at 11:01

2 Answers 2

4

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)

Sign up to request clarification or add additional context in comments.

1 Comment

You are absolutely right. Thank you. I'am ashamed not to have seen it before -_-
3

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.

1 Comment

OK, I see why it would make sense. Do you know if there is anyway to explicitely tell GCC not to do that and to create the BSS anyway ? Just for didactic purposes.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.