Below is how a typical C program memory layout would look like (program was run on macOs, but the arrangement is the same on any UNIX system). As you might expect (with stack grows downward from higher to lower addresses), the memory segments will be in the following order:
- Env & Args
- Stack
- Shared memory
- Heap
- Uninitialized data (BSS)
- Initialized data
- Text
I omitted few segments such as read-only data, init, etc. The code that produced the layout can be found at the endof the page (credit: Advanced Programming in the Unix Environment)
(args and env):
High address ----------------------------
[55] at : 0x7FF7BE0AD5D0
envp[55] at : 0x7FF7BE0AD5D0
environ[0] at : 0x7FF7BE0AD418
envp[0] at : 0x7FF7BE0AD418
environ: 0x7FF7BE0AD410
last arg at : 0x7FF7BE0AD408
first arg at
:
Stack------
: 0x7FF7BE0AD294
First variable inside main at [] ends at : 0x7FF7BE0AD2C0
faun_array[] (like 'array[]', but on stack) begins at : 0x7FF7BE0AD2B0
func_array: 0x7FF7BE0AD2A8
argc at : 0x7FF7BE0AD2A0
argv at : 0x7FF7BE0AD298
envp at (from main): frame at : 0x7FF7BE0AD254
func2 : 0x7FF7BE0AD258
func frame at static int n within func at : 0x 101E5A06C
(called 0 times): frame at : 0x7FF7BE0AD258
func (from func): frame at : 0x7FF7BE0AD234
func2
:
Shared memory--------------
: 0x 101F84000
shared memory attachment begins at : 0x 101F9C6A0
shared memory attachment ends at
:
Heap-----
: 0x6000026AD120
malloced area ends at : 0x6000026AD100
malloced area begins at
(BSS):
Uninitialized Data -------------------------
: 0x 101E5A0F4
Semaphore at : 0x 101E5A080
Cond at : 0x 101E5A0B0
Lock at [] ends at : 0x 101E5A080
array[] (uninitialized, fixed-size char * on BSS) from : 0x 101E5A070
array(uninitialized global int) at : 0x 101E5A0F0
num2 (uninitialized global char *) at : 0x 101E5A0F8
string2 extern **environ at : 0x7FF8497239A0
:
Initialized Data-----------------
(initialized global int) at : 0x 101E5A068
num (initialized global char *) at : 0x 101E5A060
string
:
Text Segment-------------
(function) at : 0x 101E55440
func2 (function) at : 0x 101E55470
func (function) at : 0x 101E54F20 main
#include <errno.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/shm.h>
#define ARRAY_SIZE 16
#define MALLOC_SIZE 32
#define SHM_SIZE 100000
#define SHM_MODE 0600
char array[ARRAY_SIZE];
char *string = "a string";
char *string2;
int num = 10;
int num2;
;
pthread_mutex_t lock;
pthread_cond_t cond;
sem_t semextern char **environ;
void func(int);
void func2(const char *);
int main(int argc, char **argv, char **envp) {
int vars;
int shmid;
char *ptr;
char func_array[ARRAY_SIZE];
= 0;
vars char **tmp = envp;
while (*tmp++) {
++;
vars}
(void)printf("High address (args and env):\n");
(void)printf("----------------------------\n");
(void)printf("envp[%d] at : 0x%12lX\n", vars, (unsigned long)&envp[vars]);
(void)printf("environ[%d] at : 0x%12lX\n", vars, (unsigned long)&environ[vars]);
(void)printf("envp[0] at : 0x%12lX\n", (unsigned long)envp);
(void)printf("environ[0] at : 0x%12lX\n", (unsigned long)environ);
(void)printf("last arg at : 0x%12lX\n", (unsigned long)&argv[argc]);
(void)printf("first arg at : 0x%12lX\n", (unsigned long)&argv[0]);
(void)printf("\n");
(void)printf("Stack:\n");
(void)printf("------\n");
(void)printf("First variable inside main at : 0x%12lX\n", (unsigned long)&vars);
(void)printf("func_array[] ends at : 0x%12lX\n", (unsigned long)&func_array[ARRAY_SIZE]);
(void)printf("func_array[] (like 'array[]', but on stack) begins at : 0x%12lX\n", (unsigned long)&func_array[0]);
(void)printf("argc at : 0x%12lX\n", (unsigned long)&argc);
(void)printf("argv at : 0x%12lX\n", (unsigned long)&argv);
(void)printf("envp at : 0x%12lX\n", (unsigned long)&envp);
("from main");
func2(0);
func
(void)printf("\n");
("Shared memory:\n");
printf("--------------\n");
printfif ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) {
(stderr, "Unable to get shared memory: %s\n",
fprintf(errno));
strerror(1);
exit}
if ((ptr = shmat(shmid, 0, 0)) == (void *)-1) {
(stderr, "Unable to map shared memory: %s\n",
fprintf(errno));
strerror(1);
exit}
("shared memory attachment begins at : 0x%12lX\n", (unsigned long)ptr);
printf("shared memory attachment ends at : 0x%12lX\n", (unsigned long)ptr+SHM_SIZE); (void)
printf("\n");
printf("Heap:\n");
printf(void)printf("-----\n");
if ((ptr = malloc(MALLOC_SIZE)) == NULL) {
(EXIT_FAILURE, "unable to allocate memory");
err/* NOTREACHED */
}
(void)printf("malloced area ends at : 0x%12lX\n", (unsigned long)ptr+MALLOC_SIZE);
(void)printf("malloced area begins at : 0x%12lX\n", (unsigned long)ptr);
(ptr);
free(void)printf("\n");
(void)printf("Uninitialized Data (BSS):\n");
(void)printf("-------------------------\n");
(void)printf("Semaphore at : 0x%12lX\n", (unsigned long)&sem);
(void)printf("Cond at : 0x%12lX\n", (unsigned long)&cond);
(void)printf("Lock at : 0x%12lX\n", (unsigned long)&lock);
(void)printf("array[] ends at : 0x%12lX\n", (unsigned long)&array[ARRAY_SIZE]);
(void)printf("array[] (uninitialized, fixed-size char * on BSS) from : 0x%12lX\n", (unsigned long)&array[0]);
(void)printf("num2 (uninitialized global int) at : 0x%12lX\n", (unsigned long)&num2);
(void)printf("string2 (uninitialized global char *) at : 0x%12lX\n", (unsigned long)&string2);
(void)printf("extern **environ at : 0x%12lX\n", (unsigned long)&environ);
(void)printf("\n");
(void)printf("Initialized Data:\n");
(void)printf("-----------------\n");
(void)printf("num (initialized global int) at : 0x%12lX\n", (unsigned long)&num);
(void)printf("string (initialized global char *) at : 0x%12lX\n", (unsigned long)&string);
(void)printf("\n");
(void)printf("Text Segment:\n");
(void)printf("-------------\n");
(void)printf("func2 (function) at : 0x%12lX\n", (unsigned long)&func2);
(void)printf("func (function) at : 0x%12lX\n", (unsigned long)&func);
(void)printf("main (function) at : 0x%12lX\n", (unsigned long)&main);
(void)printf("\n");
return EXIT_SUCCESS;
}
void func(int recurse) {
int fint;
char *msg = "from func";
/* Change this value to 0 and note how
* the location of where it is stored
* changes from the Data to BSS segment. */
static int n = 0;
(void)printf("func frame at : 0x%12lX\n", (unsigned long)&fint);
if (recurse) {
= "recursive";
msg }
(void)printf("static int n within func at : 0x%12lX\n", (unsigned long)&n);
("func (called %5d times): frame at : 0x%12lX\n", n, (unsigned long)&fint);
printf
++;
n(msg);
func2}
void func2(const char *how) {
int fint;
(void)printf("func2 (%s): frame at : 0x%12lX\n", how, (unsigned long)&fint);
(1);
func}