UtkarshPramodGupta
UtkarshPramodGupta

Reputation: 8152

Static Memory allocation in C

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

 int foo;            /* a staticly allocated variable */

 int recur(int i) {      /* a recursive function */
     int j = i;            /* a stack allocated variable within a recursive function */
     printf("recur call (i)%d: stack@ %lx\n", i, (long unsigned int) &j); /* fix this so it print
 s the address of j */
     if (i > 0) {
         return recur(i-1);
     }
     return 0;
 }

 int stuff = 7;          /* a statically allocarted, pre-initialized variable */

 int main (int argc, char *argv[]) {
     int i;            /* a stack allocated variable */
     char *buf1 = malloc(100); /* dynamically allocate some stuff */
     char *buf2 = malloc(100); /* and some more stuff */
     char *buf3 = malloc(100); /* and some more stuff */
     printf("_main  @ %lx\n", (long unsigned int) &main); /* fix to print address of main */
     printf("_recur @ %lx\n", (long unsigned int) &recur); /* fix to print address of recur */
     printf("main call (i):stack@ %lx\n", (long unsigned int) &i); /* fix to get address of the s
 tack variable */
     printf("_static foo: %lx\n", (long unsigned int) &foo); /* fix to get address of the static v
 ariable */
     printf("_static stuff: %lx\n", (long unsigned int) &stuff); /* fix to get address of a stati
 c variable */
     printf("Heap: malloc 1: %lx\n", (long unsigned int) buf1);
     printf("Heap: malloc 2: %lx\n", (long unsigned int) buf2);
     printf("Heap: malloc 3: %lx\n", (long unsigned int) buf3);
     recur(3);
     return 0;
 }

The output of this program comes out to be:

_main  @ 4005c2
_recur @ 40057d
main call (i):stack@ 7fff26397694
_static foo: 601050
_static stuff: 601048
Heap: malloc 1: 1862010
Heap: malloc 2: 1862080
Heap: malloc 3: 18620f0
recur call (i)3: stack@ 7fff2639766c
recur call (i)2: stack@ 7fff2639763c
recur call (i)1: stack@ 7fff2639760c
recur call (i)0: stack@ 7fff263975dc

Can anyone please explain followings?

Upvotes: 0

Views: 2010

Answers (2)

Manu343726
Manu343726

Reputation: 14174

First let be clear that addresses are virtual memory addresses of your process memory space. That said, the layout of a process memory space is more or less like this for a 32bit environment:

  0 +----------------------------------------+
    |             .text (code)               |
    +----------------------------------------+
    |  .data (initialized static variables)  |
    +----------------------------------------+
    | .bss (uninitialized static variables)  |
    +----------------------------------------+ <- Heap start, grows upwards
    |                  heap                  |
    +----------------------------------------+
    |                  stack                 |
3GB +----------------------------------------+ <- Stack start, grows downwards 
    |               kernel code              |
4GB +----------------------------------------+
  • Static variables addresses are not of shorter sizes, all addresses are 32bit addresses, it's only printf() truncating leading zeroes (Look at the diagram above, static variables have low addresses).

  • malloc() usually places bookeeping data in addition to the allocated buffer itself. This is implementation dependent though.

  • "int takes just 4 bytes", that depends on your system. Also the compiler could have added padding for stack frame alignment.

Upvotes: 3

ElderBug
ElderBug

Reputation: 6145

  • Every part of a program (code, data, stack ...) lives in different sections. These sections are mapped to memory regions by the OS, so the answer is that the difference you see is OS dependent. In your case, the stack happens to be mapped on a higher region, but all the addresses are still 64-bit (the address space can be less though, like 48-bit).
  • malloc() is guaranteed to return an aligned pointer. In 64-bit environment, it usually is on a 16 bytes boundary, thus the 100 bytes you allocate will be 'rounded' to 112 (7*16) for the next allocation. Also, malloc() need to keep track of allocation with additional data, so the used space will always be higher than the malloc'ed amount.
  • A major difference between stuff and foo is that one is initialized and the other one is not, thus stuff will be placed in the .data section, and foo will be placed in the .bss section (zero initialized section). This means that the two variable are unlikely to be next to each other. In your case they are near because there is nothing else.

Upvotes: 2

Related Questions