Memory Layout In C

Memory Layout of C program

Memory layout of a C program typically represented by five main segments:

  • Stack Segment: Local variables reside in stack, and it also handles function call management.
  • Heap Segment: All dynamic memory allocation (memory allocation during runtime using functions like malloc(), calloc(), …etc.) manages by heap dynamic.
  • BSS (Uninitialized Data Segment): Stores global and static variables that are initialized to zero by default.
  • DS (Initialized Data Segment): Stores global and static variables that are explicitly initialized and retain their values throughout program execution.
  • Text Segment: Contains the compiled code instructions.

Each segment of C code has its own read, write, and executable permission. These permissions are set by the operating system and the compiler. If a program tries to access the memory in a way that is not allowed, then a segmentation fault occurs.

A segmentation fault is a common problem that causes programs to crash. A core file (core dumped file) is also associated with a segmentation fault that is used by the developer to find the root cause of the crash (segmentation fault).

 

But before explaining the memory layout of C code, I also want to let you know that the actual memory layout in C might be more complex, as it depends on the processor, development tools, and underlying hardware.

 

The below diagram shows a visual representation of how RAM loads a program written in C into several segments.

 

High Addresses ---> .----------------------.
                    |      Environment     |
                    |----------------------|
                    |                      |   Functions and variable are declared
                    |         STACK        |   on the stack.
base pointer ->     | - - - - - - - - - - -|
                    |           |          |
                    |           v          |
                    :                      :
                    .                      .   The stack grows down into unused space
                    .         Empty        .   while the heap grows up. 
                    .                      .
                    .                      .   (other memory maps do occur here, such 
                    .                      .    as dynamic libraries, and different memory
                    :                      :    allocate)
                    |           ^          |
                    |           |          |
 brk point ->       | - - - - - - - - - - -|   Dynamic memory is declared on the heap
                    |          HEAP        |
                    |                      |
                    |----------------------|
                    |          BSS         |   Uninitialized data (BSS)
                    |----------------------|   
                    |          Data        |   Initialized data (DS)
                    |----------------------|
                    |          Text        |   Binary code
Low Addresses ----> '----------------------'

 

So, let’s get understand the generalized typical memory organization of C program without wasting the much time.

Stack:

  • The stack memory segment is a contiguous block of memory. It primarily consists of stack frames, stack pointer (SP), and the frame pointer (FP) or base pointer (BP)
  • When a function is called, a block is reserved on the top of the stack for local variables, function parameters, and some bookkeeping data (activation record). But when that function returns, the reserved block becomes unused and can be used the next time a function is called.
  • Stack memory segment follow the LIFO (Last-In-First-Out) structure, that means the last item pushed onto the stack is the first one to be removed. It also depends on the computer architecture that stack grows down to the lower address or not; Also, when functions are called and return, their corresponding stack frames are pushed and popped from the stack.
  • Stack grows in the direction opposite to heap.
  • A stack frame is created in the stack when a function is called and destroyed when the function returns. It also known as an activation record or activation frame. Stack frame holds information about a function’s execution and its temporary and local variables. Let’s consider an example for better understanding,
void aticleworld(int x, int y, int z)
{
    int C;
    // Some operations
}

In the above example, when function aticleworld() is called, a stack frame for aticleworld() is created. Within this stack frame, memory is allocated for the function parameters x, y, z and for the local variable C. This stack frame also stored the return address to the calling function and any necessary register values that need to be preserved across the function calls.

  • Each function call in a program creates its own stack frame that allows different instances of the same function (called separately or recursively) do not interfere with each other’s variables or execution contexts. For better understanding consider the below example code,
int fact(int a)
{
    if (a <= 1)
    {
        return 1;
    }
    else
    {
        //recursive call of function
        return (a* fact(a- 1));
    }
}

In the above example, each recursive call to function fact() creates its own stack frame. And each call to function has its own set of parameters and local variables. That means in each calling of fact() has its own local variable “a” that does not interfere with the “a” of other instances of the function fact(). It ensures the isolation between another instance of fact().

  • SP (Stack pointer) register keeps track of the top of the stack. The SP helps manage the stack efficiently by pointing to the current top of the stack. Its value change when push/pop actions are performed on the segment.

Heap:

  • Heap memory segment is used to allocate the memory at run time. That means it used for dynamic memory allocation and deallocation in a program.
  • In C language, the heap segment managed by the memory management functions like malloc, calloc, free, etc which may internally use the brk() and sbrk() system calls to adjust its size.
  • The Heap area is shared by all shared libraries and dynamically loaded modules in a process.
  • You must manage the heap memory carefully to prevent memory leaks and another issue related to dynamic memory allocation.
  • It grows and shrinks in the opposite direction of the stack.
#include <stdio.h>

int main(void)
{
    char *pStr = malloc(sizeof(char)*4); //stored in heap

    return 0;
}

 

You can also see below articles,

 

Uninitialized data segment:

  • An uninitialized data segment is also known as BSS (b​lock started by symbol).
  • Uninitialized data segment contains all uninitialized global and static variables.
  • All variables in this segment initialized by the zero (0) and pointer with the null pointer.
  • The program loader allocates memory for the BSS section when it loads the program.
#include <stdio.h>

int data1; // Uninitialized global variable stored in BSS

int main(void)
{
    static int data2;  // Uninitialized static variable stored in BSS

    return 0;
}

 

Initialized data segment:

  • The initialized data segment, also known as the data segment; it contains the explicitly initialized global and static variables.
  • Initialized data segment is distinct from the BSS (Block Started by Symbol) segment.
  • The size of this segment is determined by the size of the values in the program’s source code and does not change at run time.
  • Typically, initialized data segment has read-write permission so the value of the variable of this segment can be changed at run time.
  • This segment can be further classified into an initialized read-only area and an initialized read-write area.
#include <stdio.h>

int data1 = 10 ; //Initialized global variable stored in DS

int main(void)
{
    static int data2 = 3;  //Initialized static variable stored in DS

    return 0;
}

 

Text:

  • The text segment contains a binary of the compiled program.
  • The text segment is a read-only segment that prevents a program from being accidentally modified.
  • It is sharable so that only a single copy needs to be in memory for frequently executed programs such as text editors etc.

 

Examples:

Let see few examples to understand the memory layout of the C program. In the below examples I will use the size command to check the sizes (in bytes) of these different memory segments. The size command basically lists section sizes as well as total size for the input object file.

 

#include <stdio.h> 
  
int main(void) 
{ 
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        248          8       1216        4c0    memory-layout

 

Let us now add a static uninitialized variable and check the size.

#include <stdio.h> 
    
int main(void) 
{ 
    static int data; // Stored in uninitialized area
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        248          12       1216        4c0    memory-layout

You can see the size of the .bss (uninitialized data segment) it increased by 4 bytes by adding one uninitialized static integer variable.

 

Let us add one initialized static variable and check the size.

#include <stdio.h> 
    
int main(void) 
{ 
    static int data =10; // Stored in initialized area
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        252          8       1216        4c0    memory-layout

You can see the size of the .ds (initialized data segment) it increased by 4 bytes by adding one initialized static integer variable.

 

Let us add one uninitialized global variable and check the size.

#include <stdio.h> 
 
int data; // Stored in uninitialized area
 
int main(void) 
{ 
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        248          12       1216        4c0    memory-layout

You can see the size of the .bss (uninitialized data segment) it increased by 4 bytes by adding one uninitialized global integer variable.

 

Let us add one uninitialized global and one static variable and check the size.

#include <stdio.h> 
 
int data1; //Stored in uninitialized area
 
int main(void) 
{ 
    static int data2; //Stored in uninitialized area
   
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        248          16       1216        4c0    memory-layout

You can see the size of the .bss (uninitialized data segment) it increased by 8 bytes by adding one uninitialized global and static integer variable.

 

Let us add one initialized global and one static variable and check the size.

#include <stdio.h> 
 
int data1 = 0; //Stored in uninitialized area
 
int main(void) 
{ 
    static int data2 = 0; //Stored in uninitialized area
   
    return 0; 
}
[aticleworld@CentOS]$ gcc memory-layout.c -o memory-layout
[aticleworld@CentOS]$ size memory-layout
text       data        bss        dec        hex    filename
960        264          8       1216        4c0    memory-layout

You can see the size of the .ds (initialized data segment) it increased by 8 bytes by adding one initialized global and static integer variable.

 

Also, in the data segment, I have said that the “data segment can be further classified into the two-parts:

  • Read-only area.
  • Read-write area.

Let us see C programs to understand this classification and concept.

 

#include <stdio.h>

char str[]= "Amlendra Kumar";

int main(void)
{
    printf("%s\n",str);

    str[0]='k';

    printf("%s\n",str);

    return 0;
}

Output:

Amlendra Kumar
kmlendra Kumar

 

You can see the above example str is a global array, so it will go in the data segment. You can also see that I am able to change the value, so it has read and write permission.

Now see the other example code,

#include <stdio.h>

char *str= "Amlendra Kumar";

int main(void)
{
    str[0]='k';

    printf("%s\n",str);

    return 0;
}

You will get the compiler error here. A string literal cannot modify and goes to the read only section (normally the .rodata segment) and also similar to the string literal generally const global data also goes in .rodata segment.

 

MCQ On Memory layout in C Programs:

5 votes, 5 avg

You have 15 minutes to take the MCQ On Memory Layout

Your time has been Over.


MCQ On Memory Layout of C Programs

1 / 15

In which memory segment are constants often stored in a C program?

2 / 15

What information is NOT stored in a stack frame during a function call?

3 / 15

Which statement accurately describes the memory layout of a C program?

4 / 15

What can cause a stack overflow?

5 / 15

Which memory segment can exhibit fragmentation over time due to frequent allocation and deallocation of varying-sized memory blocks?

6 / 15

Which compiler optimization might affect the creation of stack frames during function calls?

7 / 15

Which function is used to explicitly allocate memory on the stack in C?

8 / 15

Which memory segment's growth direction in C is generally considered to be downward (towards lower memory addresses)?

9 / 15

Which segment of memory holds the compiled binary code, and is typically marked as read-only?

10 / 15

What happens if a string literal is modified in C?

11 / 15

Which register typically points to the top of the stack in many architectures?

12 / 15

What does the .bss section in the Data Segment represent?

13 / 15

In a typical memory layout of a C program, where are function instructions stored?

14 / 15

Which of the following is NOT a valid C string escape sequence?

15 / 15

What is the primary purpose of the .bss segment within the Data Segment?

Your score is

The average score is 55%

0%

 

Recommended Posts for you