I am doing some examples of stack and heap placement on an Ubuntu 14.04 VM (Linux 3.13.0-55-generic i686) and I am confused by the memory addresses for heap distribution.
The C code below allocates three 32-bit unsigned ints on the stack and three allocations on the heap of decreasing sizes, 32 bits, 16 bits, and finally 8 bits.
The following figure shows that the memory addresses for the three 32-bit ints in the stack are divided into 4 bits. uint32_t I am at 0xbffd4818, and 4 addresses later at 0xbffd481c are uint32_t j. Thus, we can see that each individual byte of memory is addressed, and therefore each 4-byte memory block has 4 memory addresses.
Looking at heap allocations, although we see that uint32_t i_ptr points to 0x99ae008 and malloc requested 4 bytes of space, so I expected uint16_t j_ptr to start at 0x99ae00c, but start at 0x99ae018. The third heap allocation for uint8_t k_ptr starts 16 bytes after uint16_t i_ptr, which also starts 16 bytes after uint32_t i_ptr.
- Is this a standard OS setup that each heap allocation is 16 bytes?
- Why does this happen regardless of the size I went through? to malloc?
- How can we put 4 bytes of information between 0x99ae008 and 0x99ae018?
C Source:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main () {
register uint32_t ebp asm ("ebp");
printf("0x%x\n", ebp);
register uint32_t esp asm ("esp");
printf("0x%x\n", esp);
uint32_t i;
printf("%p\n", &i);
uint32_t j;
printf("%p\n", &j);
uint32_t k;
printf("%p\n", &k);
uint32_t *i_ptr = malloc(4);
printf("%p\n", i_ptr);
uint16_t *j_ptr = malloc(2);
printf("%p\n", j_ptr);
uint8_t *k_ptr = malloc(1);
printf("%p\n", k_ptr);
free(i_ptr);
free(j_ptr);
free(k_ptr);
return 0;
}
CLI Output:
$ gcc -o heap2 heap2.c
$ ./heap2
0xbffd4838
0xbffd4800
0xbffd4818
0xbffd481c
0xbffd4820
0x99ae008
0x99ae018
0x99ae028
source
share