C program memory layout and understanding text, data, code, heap and stack segments

 $ vim uninitiailsed_global_variable.c 
#include <stdio.h>
int uninitilised_global_variable;
int main(int argc, char **argv) { return 0;
 $ gcc -o uninitiailsed_global_variable uninitiailsed_global_variable.c 
 $ $ size uninitiailsed_global_variable text data bss dec hex	filename 1017 272 8 1297 511	uninitiailsed_global_variable

.data segment

The .data segment contains any global or static variables which have a pre-defined value and can be modified. That is any variables that are not defined within a function (and thus can be accessed from anywhere) or are defined in a function but are defined as static so they retain their address across subsequent calls.

 $ vim initiailsed_global_variable.c 
#include <stdio.h>
int initilised_global_variable = 78;
int main(int argc, char **argv) { printf("address of : initilised_global_variable = %p\n", &initilised_global_variable); return 0;
 $ size initiailsed_global_variable text data bss dec hex	filename 1156 280 4 1440 5a0	initiailsed_global_variable

Now lets run this program to check, what is the address assigned to our initiailsed global integer variable as,

 $ address of : initilised_global_variable = 0x804a01c 

Now, lets check using nm tool what is the predefined address space our program got from the compiler as,

$ nm -s a.out
0804a020 B __bss_start
0804a020 b completed.7200
0804a014 D __data_start
0804a014 W data_start
08048350 t deregister_tm_clones
080483c0 t __do_global_dtors_aux
08049f0c t __do_global_dtors_aux_fini_array_entry
0804a018 D __dso_handle
08049f14 d _DYNAMIC
0804a020 D _edata
0804a024 B _end
080484a4 T _fini
080484b8 R _fp_hw
080483e0 t frame_dummy
08049f08 t __frame_dummy_init_array_entry
080485e4 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__
080484f0 r __GNU_EH_FRAME_HDR
080482ac T _init
08049f0c t __init_array_end
08049f08 t __init_array_start0804a01c D initilised_global_variable080484bc R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__ w _Jv_RegisterClasses
080484a0 T __libc_csu_fini
08048440 T __libc_csu_init U __libc_start_main@@GLIBC_2.0
0804840b T main U printf@@GLIBC_2.0
08048380 t register_tm_clones
08048310 T _start
0804a020 D __TMC_END__
08048340 T __x86.get_pc_thunk.bx

output of nm shows that we got the address for “int initilised_global_variable” i.e. 0x804a01c which is predefined as seen in “nm -s” in bold ( just before _IO_stdin_used in above nm output ) and after data segment address has started at “0804a014 D __data_start”

 $ local_initialised_and_uninitialised_variable.c 
#include <stdio.h>
int main(int argc, char **argv) { int local_initialised_variable = 78; int local_variable; return 0;
 gcc -o local_initialised_and_uninitialised_variable local_initialised_and_uninitialised_variable.c 
 $ size local_initialised_and_uninitialised_variable text data bss dec hex	filename 1017 272 4 1293 50d	local_initialised_and_uninitialised_variable 
 $ vim variables_in_stack.c 
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
//check cat /proc/pid/maps to know address printed belogs to stack
int main(int argc, char **argv) { int local_initialised_variable = 78; int local_uninitialised_variable; printf("Address of : local_initialised_variable = %p\n", &local_initialised_variable); printf("Address of : local_uninitialised_variable = %p\n", &local_uninitialised_variable); //create a infinite loop so we can check address mapped in /proc while(1); //this is just to identify where we got the address mapped return 0;
 $ gcc -o variables_in_stack variables_in_stack.c 
 $ ./variables_in_stack
Address of : local_initialised_variable = 0xbf961c34
Address of : local_uninitialised_variable = 0xbf961c38

Now, lets identify from proc map of a process we created just now to identify which area the addresses we printed belongs to,

READ  C program to Print hex values of characters in string

know the process Id as program running above from another terminal as,

 $ $ ps -ax | grep variables_in_stack 6971 pts/9 R+ 1:37 ./variables_in_stack 

We can see, we have got 6971 as process Id, now lets check the process map from proc file system as,

 $ cd /proc/6971/ 
 $ ls 
 $ sudo cat maps
08048000-08049000 r-xp 00000000 08:06 13894234 variables_in_stack
08049000-0804a000 r--p 00000000 08:06 13894234 variables_in_stack
0804a000-0804b000 rw-p 00001000 08:06 13894234 variables_in_stack
09859000-0987a000 rw-p 00000000 00:00 0 [heap]
b7539000-b76e9000 r-xp 00000000 08:06 18879084 /lib/i386-linux-gnu/libc-2.23.so
b76e9000-b76eb000 r--p 001af000 08:06 18879084 /lib/i386-linux-gnu/libc-2.23.so
b76eb000-b76ec000 rw-p 001b1000 08:06 18879084 /lib/i386-linux-gnu/libc-2.23.so
b76ec000-b76ef000 rw-p 00000000 00:00 0
b771b000-b771d000 rw-p 00000000 00:00 0
b771d000-b771f000 r--p 00000000 00:00 0 [vvar]
b771f000-b7720000 r-xp 00000000 00:00 0 [vdso]
b7720000-b7742000 r-xp 00000000 08:06 18874426 /lib/i386-linux-gnu/ld-2.23.so
b7742000-b7743000 rw-p 00000000 00:00 0
b7743000-b7744000 r--p 00022000 08:06 18874426 /lib/i386-linux-gnu/ld-2.23.so
b7744000-b7745000 rw-p 00023000 08:06 18874426 /lib/i386-linux-gnu/ld-2.23.so
bf942000-bf963000 rw-p 00000000 00:00 0 [stack]

As we can see above, the address printed by our program are 0xbf961c34 and 0xbf961c38 and the stack memory allocated for this program ranges from bf942000 to bf963000 . Which shows that the local variables resides in the stack memory of a program.

Leave a Reply

Your email address will not be published. Required fields are marked *