This question already has an answer here:
In a simple C program, if I
malloc a point that points to a variable or array, where is this part of memory allocated to in terms of memory map? I am very new to computer programming, so I am not sure how different variables are stored differently in the memory.
Also, where would a global variable (e.g.
int x = 5) be stored to in the memory?
Lastly, is there any material that talks about how C language interacts with the low level hardware? What I found online are all related to C syntax, but I am too noob to read compiler books.
Please let me know if this is not clear.
Best How To :
Consider this example:
int global_x = 5;
char* buf = malloc(100);
While the following descriptions are not always the case (particularly in tiny embedded implementations), a typical program on a modern platform will be layed out as follows:
global_x is an initialized global variable. It is typically stored in a
.data section in the executable file, and when the program is loaded, it lives in read-write, non-executable section of memory along side your program text.
global_y is an uninitialized global variable. Space is reserved in the
.bss section of the program, and takes up no space in the executable file. It lives in a simliar section as above when loaded.
local_a is a local (or "automatic") variable that lives in the call stack of main. Its lifetime is constrained to the duration of execution in that function. (i.e. Once the function returns, the variable does not exist anymore, and is trashed.)
buf points to a dynamically-allocated buffer of 100 bytes that is pulled from the heap. The heap is an area of memory that usually will expand as needed to accomodate the memory requirements of the application. When heap space is exhausted (as determined by
malloc and supporting library functions), additional memory will be requested from the operating system (e.g.
mmap on Linux).
On Linux, you can look at
/prod/[pid]/maps to see the memory mapping for the process
[pid]. For example:
$ cat /proc/30009/maps
00400000-0040c000 r-xp 00000000 fd:01 268784 /usr/bin/cat
0060b000-0060c000 r--p 0000b000 fd:01 268784 /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 fd:01 268784 /usr/bin/cat
01a7a000-01a9b000 rw-p 00000000 00:00 0 [heap]
365ec00000-365ec20000 r-xp 00000000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee1f000-365ee20000 r--p 0001f000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee20000-365ee21000 rw-p 00020000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee21000-365ee22000 rw-p 00000000 00:00 0
365f000000-365f1b4000 r-xp 00000000 fd:01 263128 /usr/lib64/libc-2.18.so
365f1b4000-365f3b4000 ---p 001b4000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3b4000-365f3b8000 r--p 001b4000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3b8000-365f3ba000 rw-p 001b8000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3ba000-365f3bf000 rw-p 00000000 00:00 0
7f685162b000-7f6857b54000 r--p 00000000 fd:01 302750 /usr/lib/locale/locale-archive
7f6857b54000-7f6857b57000 rw-p 00000000 00:00 0
7f6857b6c000-7f6857b6d000 rw-p 00000000 00:00 0
7fffa6f09000-7fffa6f2a000 rw-p 00000000 00:00 0 [stack]
7fffa6ffe000-7fffa7000000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
We see that there are three parts of
/usr/bin/cat mapped in at
By looking at the output of
readelf -a /usr/bin/cat you can identify which sections correspond to the segments that are loaded at those addresses. This is left as an excercise to the reader :-)