Came across this article http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/, and the pictorial illustration is very clear. Here’s a short program to confirm the layout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>

int main()
{
int x;
printf("%p\n", &x);
void *p = mmap(NULL, 1, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
printf("%p\n", p);

printf("%p\n", sbrk(0));

malloc(1);
printf("%p\n", sbrk(0));

malloc(1);
printf("%p\n", sbrk(0));

return 0;
}

The output on my box is:

1
2
3
4
5
6
0x7ffdb10979a8
0x7fb6f6cde000
0x7fb6f6cdd000
0x2030000
0x2051000
0x2051000

Some observation (mentioned in the article):

  • stack starts from high address
  • mmap region is placed below stack, and grows downwards
  • mmap anonymous memory is page (4k) align
  • heap starts from low address, and grows upwards