An understanding of memory layout in C – Part 2

The interested reader can peruse the first part of this series here – <An understanding of memory layout in C – Part 1>

From the previous article it was seen how the different layers of memory are aligned for a C program that runs on a system.

A “C” Program is  provided below which progressively adds various variables and looks at different instances and how memory changes with the addition of different types of variables.

/* function with no variables added */

int main () {

return 0;

}

now compile via gcc to obtain the memory layout with the “size” command

$ gcc Test_memory_Layout.c -o Test_memory_Layout_barebones.o

$ size Test_memory_Layout.o

text     data         bss         dec         hex     filename

1099      544           8        1651         673     Test_memory_Layout.o

Note: Analyzing the different segments, .text/.data and .bss segments are present. The .stack and .heap segments are not shown by the “size command”. This is because – both the stack and heap are run-time allocations and are dynamic and not shown at compilation time.

Adding Global variables to the program

/* global variables added to function */

#include <stdio.h>

#include <stdlib.h>

int value_int; /* value stored in .BSS – unintialized data segment – init to zero*/

int value_int_1 = 10; /* value stored in initialized data segment */

int main () {

return 0;

}

$ gcc Test_memory_Layout.c -o Test_memory_Layout.o

$ size Test_memory_Layout.o

text      data      bss       dec      hex  filename

1099     548       12      1659     67b  Test_memory_Layout.o

it can be seen that the initialized data segment and the bss segment is increased by 4.

 

Add static variables – initialized and un-initialized into code

/* static variables added to function */

int value_int; /* value stored in .BSS – unintialized data segment – init to zero*/

int value_int_1 = 10; /* value stored in initialized data segment */

int main () {

static int value2; /* value stored in .BSS – uninitialized data segment – init to zero */

static int value3 = 5; /* value stored in initialized data segment */

return 0;

}

$ gcc Test_memory_Layout.c -o Test_memory_Layout.o

$ size Test_memory_Layout.o

text         data      bss       dec      hex  filename

1099        552       16      1667     683  Test_memory_Layout.o

it is seen that the .data and ,bss sections increased by size 4 again

Adding an un-initialized global array

int value_int;

int value_int_1 = 10;

int value[10];

int main () {

static int value2; /* value stored in .BSS – uninitialized data segment – init to zero */

static int value3 = 5; /* value stored in initialized data segment */

return 0;

}

$ gcc Test_memory_Layout.c -o Test_memory_Layout.o

$ size Test_memory_Layout.o

text         data      bss       dec      hex  filename

1099        552       80      1731     6c3  Test_memory_Layout.o

As seen above – the .BSS segment increased to accomodate the un-initialized array

Add an initialized array to the midst

int value_int;

int value_int_1 = 10;

int value[10];

int val[2] = {1, 2};

int main () {

static int value2; /* value stored in .BSS – uninitialized data segment – init to zero */

static int value3 = 5; /* value stored in initialized data segment */

return 0;

}

$ gcc Test_memory_Layout.c -o Test_memory_Layout.o

$ size Test_memory_Layout.o

text         data      bss       dec      hex  filename

1099        564       80      1743     6cf   Test_memory_Layout.o

And as expected the .data segment increased to accomodate the initialized array.

All constant variables usually go into the .text segment or .rodata segment. #define variables are not allocated memory. The preprocessor replaces the #define value in code whenever it is used. Hence, #define values form part of text segment

How to debug a program with gdb

Comments

  1. Pingback: An understanding of memory layout in C – Part 1 | Hitch Hiker's Guide to Learning

Leave a Reply

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