Issue
I have a code with several uninitialized global variables, for the sake of simplicity, let's say 3:
int global_uninitialized_0;
int global_uninitialized_1;
int global_uninitialized_2;
When compiling this code, the size of bss is reported by size is 16.
If I added more global uninitialized variables, the bss grows as expected. Yet, if I use an array of ints, it grows more than I would expect:
int global_uninitialized_0;
int global_uninitialized_1;
int global_uninitialized_2[4];
When compiling this code, the size of bss is reported by size is 48. Notice, when using an array of 3 elements, the bss grows as expected as well.
Why this discrepancy? I'd say there is some sort of alignment, but I couldn't find anything related to it.
Solution
When compiling your test for x86_64
, I observe the following layout:
readelf -Ws t.o | grep ' global'
2: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 global_uninitialized_0
3: 0000000000000004 4 OBJECT GLOBAL DEFAULT 3 global_uninitialized_1
4: 0000000000000010 16 OBJECT GLOBAL DEFAULT 3 global_uninitialized_2
The size of .bss
(32 bytes here) makes perfect sense when you consider that the global_uninitialized_2
starts 16 bytes into the .bss
section, so the question is: why did the compiler decide to leave an 8-byte hole between global_uninitialized_1
and global_uninitialized_2
?
I am guessing that GCC tries to align this array on 16-byte boundary for cache alignment purpose.
If you change the definition of global_uninitialized_2
to only require 4-byte alignment:
__attribute__((aligned(4))) int global_uninitialized_2[4];
then you get a 24-byte .bss
and the array is allocated immediately after the single int
.
Answered By - Employed Russian Answer Checked By - Marilyn (WPSolving Volunteer)