The general way in which C programs are loaded into the memory is in the following format:
When we compile a C Program, a final executable (i.e. in UNIX, traditional ‘a.out’) is created. This executable when executed is first loaded into the RAM by a program loader and the executable program is known as a “process”. A process can be divided into several blocks or segments and can typically have an arrangement as shown in the above figure. The blocks are named as follows:
- Text Segment
- Initialized read-only data segment
- Initialized read-write data segment
- Uninitialized data segment
To understand the above divided segments, let us take an example program as reference in this post.
Program – 1:
int a = 5;
const int i = 5;
int main( )
int *ptr = malloc( 50 );
- Text Segment: The text segment of the process contains the actual machine instructions that are executed by the hardware. This segment is read-only segment so that the process cannot modify its instructions.
- Initialized read-only data segment: This segment contains data elements that are initialized by the program and are read-only while the process is executing. In our program above, the constant variable ‘i‘ is stored in this segment. Note that ‘i‘ is a global variable.
- Initialized read-write data segment: This segment contains data elements that are initialized by the program. For example, in our program above, the variable ‘a‘ is stored in this segment. Their values may be changed during the process execution. Note that ‘a‘ is a global variable.
- Uninitialized data segment: This segment contains elements that are not initialized by the program but are set to zero before the process starts execution. For example, in our program above, the variable ‘b‘ and the array ‘data‘ are stored in this segment. The values of these variables may change during the execution of the processes. Note that these variables are global variables. Uninitialized data segment is also called BSS – which stands for Block Started by Symbol.
- Stack: The stack is used dynamically to store the automatic variables. For example in our program above, the variable ‘x‘ is stored in the stack. The stack appears and disappears during run-time whenever a function is called and returned. The stack frame is a part of the stack dedicated for a single function. When several such functions are called one after other, the stack frames starts building one on the other. We call this as “Stack is Growing”. Once, each function starts returning, the stack frame allocated for that particular function starts disappearing. The arguments to a function, the return address for a function (to return after a successful call) and local or automatic variables in a program are stored in stack.
- Heap: Heap is used while a process is running to allocate more data space dynamically to the process. For example, in our program, ‘ptr‘ points to dynamically allocated memory from heap using the ‘malloc( )’ library function.
As can be seen from the figure that, a gap is shown between the heap and the stack to indicate that many operating systems leave some room between these two portions, so that both can grow dynamically.
Subhash.K.U, Principal Mentor, Subhash Programming Classes