Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

understanding size command for data bss segment in C

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?

like image 237
GorvGoyl Avatar asked Mar 26 '15 21:03

GorvGoyl


1 Answers

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.

like image 188
teppic Avatar answered Sep 20 '22 16:09

teppic