As we can observe in the above figure, the C program consists of the following sections in the program:
- Text segment
- Initialized data segment
- Uninitialized data segment
- Stack
- Heap
Let's understand each section one by one.
1. Text segment
The section of text is commonly referred to as the code segment. During program compilation, it generates an executable file such as a.out, .exe, etc., which is then saved in the text or code area of the RAM memory. Storing instructions on the hard disk results in slower access speeds due to the serial communication nature of hard disks, causing delays in data retrieval. On the other hand, RAM is directly linked to the data and address buses, enabling quicker access to data stored in RAM.
2. Data section
The information utilized within our program will be housed in the data segment. While variables defined within the main function reside in the stack, those declared outside the main function are stored in the data segment. Variables within the data segment can take the form of initialized or uninitialized, and they may be either local or global. As a result, the data segment is categorized into four groups: initialized, uninitialized, global, and local.
Let's grasp this situation with an illustration.
#include<stdio.h>
int var1;
int var2 = 10;
void function1()
{
printf("I am function1");
}
int main()
{
function1();
return 0;
}
In the provided code snippet, the variables var1 and var2 are defined outside the main function. var1 is uninitialized, while var2 is initialized. Due to their placement outside the main function, these variables have a global scope and can be accessed from any part of the program as they are not stored on the stack within the main function.
The data portion is divided into two segments:
- Uninitialized data segment
- Initialized data segment
Uninitialized data segment
The uninitialized data segment, commonly referred to as the .bss segment, is responsible for storing all the unassigned global, local, and external variables. In cases where global, static, and external variables lack initialization, they are automatically set to a default value of zero.
The .bss section is an abbreviation for Block Started by Symbol. This segment houses the object file that stores all statically allocated variables. Statically allocated objects refer to those variables that are not explicitly initialized and are automatically set to zero. In the provided code snippet, var1 is an example of an uninitialized variable, hence it resides in the uninitialized data section.
Let's examine a few instances of uninitialized data segment.
#include<stdio.h>
char a; // uninitialized global variable..
int main()
{
static int a; // uninitialized static variable..
return 0;
}
Initialized data segment
An initialized data segment is commonly referred to as the data segment. It represents a reserved memory space within a program's virtual address, housing all global and static variables that are explicitly set by the developer.
The values of variables within a data segment are not static, meaning they are subject to changes during runtime. This data segment can be categorized into the following classifications:
- Constant read-only area: Variables in this section are unalterable.
- Mutable read-write area: This section allows variables to be modified as needed.
For instance, global variables such as char str = "logic practice" and int a=45; are typically placed in the initialized read-write section of memory. When a global variable like const char* string = "logic practice" is declared, the actual string "logic practice" gets stored in the initialized read-only memory region, while the character pointer variable itself is stored in the initialized write section.
#include<stdio.h>
char string[] = "logic practice"; // global variable stored in initialized data segment in read-write area..
int main()
{
static int i = 90; // static variable stored in initialized data segment..
return 0;
}
3. Stack
When a function is defined and invoked, the stack frame is employed. Variables declared within the function are stored in the stack, including function arguments as they are integral to the function. This form of memory allocation is termed as static memory allocation since all function variables are specified within the function, with variable sizes determined during compilation. The stack segment holds significant importance in memory management by generating a new stack frame each time a function is called.
Stack is additionally employed in recursive functions. This occurs when a function repeatedly calls itself within the same function, triggering a stack overflow situation that results in a segmentation fault error within the program.
4. Heap
Heap memory is employed for dynamic memory allocation. It starts from the end of the uninitialized data segment and expands towards higher addresses. Memory allocation in the heap is done using the malloc and calloc functions. All shared libraries and dynamically loaded modules can access heap memory. To release memory from the heap, the free function is utilized.
#include<stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = (int*)malloc(sizeof(int)) ; // memory gets allocated in the heap segment.
return 0;
}