understanding size command for data bss segment in C
Asked Answered
S

3

6

I'm getting unexpected output from size command.

Afaik initialized global and static variables stored in data segment and uninitialized and initialized to 0 global/static variables stored in bss segment.

printf("%d",sizeof(int)); gives int size 4. However, bss and data segment is not increasing accordingly to 4.

#include <stdio.h>
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

#include <stdio.h>
int g; //uninitialised global variable so, stored in bss segment
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2528   14864    3a10 memory-layout.exe

why bss increased by 16 (2528 - 2512) instead of 4? (in above code)

#include <stdio.h>
int g=0; //initialised to 0 so, stored in bss segment
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

there is no increment in bss in spite of using global variable. why's that?

 #include <stdio.h>
int main()
{   static int g; //should be on bss segment
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.ex
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

no increment in bss segment in spite of using static variable, why?

and I have one more question, what dec represents here?

Sundried answered 26/3, 2015 at 21:29 Comment(11)
Use the od or nm commands to list object/executable files, their sections and their sections.Walkout
@a3f what's the significanceSundried
@JoachimPileborg no od command found in MinGWSundried
case int g = 0; - as initialized global is not stored in BSS.Gallantry
@AntoJurković read here about this en.wikipedia.org/wiki/Data_segmentSundried
Didn't know about that. I was checking Peter van der Linden book "Expert C Programming". Anyway, BSS says " An implementation may also assign statically-allocated variables and constants initialized with a value consisting solely of zero-valued bits to the BSS section." So it seems it is implementation dependent.Gallantry
Seems to me dec = text + data + bss. And` hex` is same as dec but ...in hex. ;)Tynan
Look in the linker map to see where these variables actually went. It looks like your linker is increasing the sizes of sections in 16-byte increments instead of 4-byte increments. You could experiment with this by doing int a; int b; int c; int d; int e; in stages and noting when it increases in size. The int g = 0; case seems to suggest it is going into .data and didn't increase because there was already room as we just saw.Kibitz
Also bear in mind that variables may be optimized out if the compiler realizes they are unused; this could be happening in cases 2 and 3.Kibitz
It is implementation-dependent whether BSS and DATA even exist of course. I have used systems where int g = 0; goes in DATA and some where it goes in BSS. Of course the sensible thing would be for it to go in BSS , IDK whether the compiler vendor just couldn't be bothered or what. In one of my code bases I ended up having to write int g ZERO_INITIALIZED; where that is a macro that expands to either blank or to = { 0 } depending on which compiler/platform is in useKibitz
case 1 : uninitialized global : value is in BSS. Linker is allocating space in BSS at 16 byte boundaries. Hence, BSS size is increased by 16. case 2 : initialized to zero: compiler is not considering this as a case of default initialization and puts it in Data segment along with other initialized global variables. Hence, no increase in BSS case 3: static variable inside a function. Compiler knows you are not using this variable. No space allocated in BSS. In previous cases, since these were global variable, compiler cannot optimize it out. dec : total size = text + bss + data in decimal.Sterner
D
2

The first thing to consider is memory alignment. Variables and sections can be padded to make them sit on address boundaries. In the second example you are seeing an increase of 16 from the first, which suggests padding for 16-byte boundaries (2512 / 16 = 157, 2528 / 16 = 158). This is entirely implementation dependent.

As far as C is concerned, the second example differs from the third because the compiler cannot know if int g is a definition or just a declaration for an integer defined in another file (where it could be any value). It leaves a reference for the linker to deal with instead, which may lead to differences in padding.

In the third example, g is explicitly defined and set to 0, so the compiler knows to put this in the BSS section.

It's possible to demonstrate this with the generated assembly from my system:

with int g (no BSS section is defined in this case)

.comm   g,4,4

This is a instruction for the linker to deal with the symbol, as the compiler cannot fully determine what to do with it.

with int g = 0

    .bss
    .align 4
    .type   g, @object
    .size   g, 4
g:
    .zero   4

Here the compiler knows exactly what to do and so defines a BSS section for the symbol.

In my case, the linker resolves these identically. Both are placed in the BSS section at the same address, and so there is no difference in BSS size. You can examine the layout with a utility like nm.

nm -n file2 file3 | grep g$

000000000060103c B g
000000000060103c B g

i.e. on this system g is at the same address. Alternatively, with a debugger:

(gdb) info symbol 0x60103c
g in section .bss of /tmp/file2

Note also that in the final example the variable can be optimised out, since it has internal linkage.

As for dec, it is simply the sum of the sections in decimal.

Degression answered 30/3, 2015 at 22:9 Comment(0)
D
1

This is from gcc on linux:

No Variable
   text    data     bss     dec     hex filename
    915     248       8    1171     493 none.out
Uninitialized Global
   text    data     bss     dec     hex filename
    915     248      12    1175     497 u_g.out
Initialized Global to 123
   text    data     bss     dec     hex filename
    915     252       8    1175     497 i_g.out
Initialized Local to 124
   text    data     bss     dec     hex filename
    915     252       8    1175     497 i_l.out
Initialized Global to 0
   text    data     bss     dec     hex filename
    915     248      12    1175     497 i_g_0.out
Initialized Local to 0
   text    data     bss     dec     hex filename
    915     248      12    1175     497 i_l_0.out

This is from mingw64 on Windows:

No Variable
   text    data     bss     dec     hex filename
   3173    1976     448    5597    15dd none.out
Uninitialized Global
   text    data     bss     dec     hex filename
   3173    1976     464    5613    15ed u_g.out
Initialized Global to 123
   text    data     bss     dec     hex filename
   3173    1976     448    5597    15dd i_g.out
Initialized Local to 124
   text    data     bss     dec     hex filename
   3173    1976     448    5597    15dd i_l.out
Initialized Global to 0
   text    data     bss     dec     hex filename
   3173    1976     480    5629    15fd i_g_0.out
Initialized Local to 0
   text    data     bss     dec     hex filename
   3173    1976     480    5629    15fd i_l_0.out

So although I don't have a final answer to the question (wouldn't fit in a comment), results make me suspect the executable file format of Windows and/or MinGW (i.e. not gcc).

Deplane answered 3/4, 2015 at 12:50 Comment(0)
X
0

BSS only contains static and global values which are not explicitly initialized. Even though you are explicitly initializing it to the same value to which it would be initialized if it were not initialized explicitly, the fact of explicit initialization means it doesn't belong in bss.

Xylotomous answered 5/4, 2015 at 7:26 Comment(5)
This is incorrect. Data initialised to zero may be in the BSS section.Degression
@teppic, even if it were true that it may be in the BSS segment, the fact that it is explicitly initialized (even to 0) means that it need not be in the BSS segment. The only case in which it can be said that it must be in BSS is when it is not explicitly initialized global static.Xylotomous
It's up to the implementation, it doesn't have to use BSS for anything.Degression
How about this: if it has BSS and it stores uninitilized data in BSS (which what BSS is intended for), then storing data initialized to 0 in BSS is an optional optimization.Xylotomous
The problem is it's all optional, there's no standard and it's defined by the implementation (both hardware and compiler). BSS is more about storing data that should be zero, without having to allocate the space in the binary.Degression

© 2022 - 2024 — McMap. All rights reserved.