Skip to main content

Memory Allocation/Segmentation in C/C++

Memory Allocation/Segmentation in C/C++

| stack |
| vv |
| |
| |
| ^^ |
| heap |
| bss |
| data |
| text |
address 0

Segment Description
Codetext segment Often referred to as the text segment, this is the area in which the executable instructions reside.  For example, Linux/Unix arranges things so that multiple running instances of the same program share their code if possible.  Only one copy of the instructions for the same program resides in memory at any time.  The portion of the executable file containing the text segment is the text section.
Initialized data – data segment Statically allocated and global data that are initialized with nonzero values live in the data segment.  Each process running the same program has its own data segment.  The portion of the executable file containing the data segment is the data section.
Uninitialized data – bss segment BSS stands for ‘Block Started by Symbol’.  Global and statically allocated data that initialized to zero by default are kept in what is called the BSS area of the process.  Each process running the same program has its own BSS area.  When running, the BSS data are placed in the data segment.  In the executable file, they are stored in the BSS section.  For Linux/Unix the format of an executable, only variables that are initialized to a nonzero value occupy space in the executable’s disk file.
Heap The heap is where dynamic memory (obtained by malloc(), calloc(), realloc() and new for C++) comes from.  Everything on a heap is anonymous, thus you can only access parts of it through a pointer. As memory is allocated on the heap, the process’s address space grows.  Although it is possible to give memory back to the system and shrink a process’s address space, this is almost never done because it will be allocated to other process again.   Freed memory (free() and delete) goes back to the heap, creating what is called holes.   It is typical for the heap to grow upward.  This means that successive items that are added to the heap are added at addresses that are numerically greater than previous items.  It is also typical for the heap to start immediately after the BSS area of the data segment.  The end of the heap is marked by a pointer known as the break. You cannot reference past the break. You can, however, move the break pointer (via brk() and sbrk() system calls) to a new position to increase the amount of heap memory available.
Stack The stack segment is where local (automatic) variables are allocated.  In C program, local variables are all variables declared inside the opening left curly brace of a function body including the main() or other left curly brace that aren’t defined as static.  The data is popped up or pushed into the stack following the Last In First Out (LIFO) rule.  The stack holds local variables, temporary information, function parameters, return address and the like.  When a function is called, a stack frame (or a procedure activation record) is created and PUSHed onto the top of the stack. This stack frame contains information such as the address from which the function was called and where to jump back to when the function is finished (return address), parameters, local variables, and any other information needed by the invoked function. The order of the information may vary by system and compiler.  When a function returns, the stack frame is POPped from the stack.  Typically the stack grows downward, meaning that items deeper in the call chain are at numerically lower addresses and toward the heap.

Example code:

#include <iostream>
using namespace std;
int f1;         //bss (where is data(variable&constant) stored)
int f2=0;       //bss
int f3=1;       //data
static int f4 = 0;    //bss
static int f5 = 1;    //data
int main ()
int a[2];       //stack
int b1;          //stack
int b2 = 0;     //stack
int b3 = 1;     //stack
char b5[]= “abc”;      //stack
static int c[2];      //uninitialized static, bss (initialized to 0 by default)
static int d1;         //uninitialized static, bss (initialized to 0 by default)
static int d2 = 0;     //zero initialization = uninitialized, bss
static int d3 = 1;     //nonzero init, data
static int d4 = 1;     //nonzero init, data
const int e1 = 0;      //stack
const int e2 = 1;      //stack
char *p1 = “abc”;      //p1: stack, *p1 (“abc”): data
char *p2 = “abcd”;      //p2: stack, *p2 (“abcd”): data
static int *p3 = &b1;  //p3:bss
static int *p4;  //p4:bss, *p4: 0;
int *p5 = NULL; //p5: stack, *p5: 0
static int *p6 = NULL; //p6:bss, 0
int *p7;               //p7: stack,
static char * p8 = “abc”;    //p8:data, *p8 (“abc”): data, same as *p1
int b4 = 1;
static int * p9 = &b4; //p9:bss
d1 = 1;    //d1: bss
int *p10 = (int*)malloc(sizeof(int));   //p10: stack, *p10:heap
*p10 = 1;
static char *p11 = (char*)malloc(sizeof(char)); //p11: bss, *p11:heap
*p11 = ‘a’;
printf(“Local variables:\n\n”);
printf(“int a[0]: %d (stack)\n”,a);
printf(“int a[1]: %d (stack)\n”,a+1);
printf(“int b1: %d (stack)\n”,&b1);
printf(“int b2=0: %d (stack)\n”,&b2);
printf(“int b3=1: %d (stack)\n”,&b3);
printf(“char b5[]=\”abc\”: %d (*b5 \”abc\”, stack)\n”,b5);
printf(“const int e1=0: %d (stack)\n”,&e1);
printf(“const int e2=1: %d (stack)\n”,&e2);
printf(“char * p1=\”abc\”: %d (p1, stack)\n”,&p1);
printf(“char * p2=\”abc\”: %d (p2, stack)\n”,&p2);
printf(“int * p5 = NULL: %d (p5, stack)\n”,&p5);
printf(“int * p7: %d (p7, stack)\n”,&p7);
printf(“int *p10 = (int *)malloc(int): %d (p10,stack)\n”,&p10);
printf(“static int c[0]: %d (bss)\n”,c);
printf(“static int c[1]: %d (bss)\n”,c+1);
printf(“static int d1: %d (bss)\n”,&d1);
printf(“static int d2=0: %d (bss)\n”,&d2);
printf(“static int * p3 = &b1: %d (p3, bss)\n”,&p3);
printf(“static int * p4: %d (p4, bss)\n”,&p4);
printf(“static int * p6 = NULL: %d (p6, bss)\n”,&p6);
printf(“static int * p9 = &b4, b4=1: %d (p9, bss)\n”,&p9);
printf(“d1 = 1: %d (bss)\n”,&d1);
printf(“static int *p11 = (int*)malloc(int): %d (p11,bss)\n”,&p11);
printf(“static int d3=1: %d (data)\n”,&d3);
printf(“static int d4=1: %d (data)\n”,&d4);
printf(“static char * p8 = \”abc\”: %d (p8, data)\n”,&p8);
printf(“char * p1=\”abc\”: %d (*p1 \”abc\”, data)\n”,p1);
printf(“static char * p8 = \”abc\”: %d (*p8 \”abc\”, data)\n”,p8);
printf(“char * p2=\”abcd\”: %d (*p2 \”abcd\”, data)\n”,p2);
printf(“static int * p4: %d (*p4, 0)\n”,p4);
printf(“int * p5 = NULL: %d (*p5, 0)\n”,p5);
printf(“int *p10 = (int *)malloc(int): %d (*p10:1,Heap)\n”,p10);
printf(“static char *p11 = (int*)malloc(int): %d (*p11:’a',Heap)\n”,p11);
printf(“\n\nGlobal variables:\n”);
printf(“int f1: %d (bss)\n”,&f1);
printf(“int f2=0: %d (bss)\n”,&f2);
printf(“static int f4: %d (bss)\n”,&f4);
printf(“int f3=1: %d (data)\n”,&f3);
printf(“static int f5=1: %d (data)\n”,&f5);
return 0;


Local variables:
int a[0]: 2359152 (stack)
int a[1]: 2359156 (stack)
int b1: 2359148 (stack)
int b2=0: 2359144 (stack)
int b3=1: 2359140 (stack)
char b5[]=”abc”: 2359136 (*b5 “abc”, stack)
const int e1=0: 2359132 (stack)
const int e2=1: 2359128 (stack)
char * p1=”abc”: 2359124 (p1, stack)
char * p2=”abc”: 2359120 (p2, stack)
int * p5 = NULL: 2359116 (p5, stack)
int * p7: 2359112 (p7, stack)
int *p10 = (int *)malloc(int): 2359104 (p10,stack)
static int c[0]: 4468840 (bss)
static int c[1]: 4468844 (bss)
static int d1: 4468856 (bss)
static int d2=0: 4468872 (bss)
static int * p3 = &b1: 4468888 (p3, bss)
static int * p4: 4468904 (p4, bss)
static int * p6 = NULL: 4468920 (p6, bss)
static int * p9 = &b4, b4=1: 4468936 (p9, bss)
d1 = 1: 4468856 (bss)
static int *p11 = (int*)malloc(int): 4468952 (p11,bss)
static int d3=1: 4452360 (data)
static int d4=1: 4452364 (data)
static char * p8 = “abc”: 4452368 (p8, data)
char * p1=”abc”: 4456448 (*p1 “abc”, data)
static char * p8 = “abc”: 4456448 (*p8 “abc”, data)
char * p2=”abcd”: 4456452 (*p2 “abcd”, data)
static int * p4: 0 (*p4, 0)
int * p5 = NULL: 0 (*p5, 0)

int *p10 = (int *)malloc(int): 212064 (*p10:1,Heap)
static char *p11 = (int*)malloc(int): 212168 (*p10:’a',Heap)

Global variables:
int f1: 4468752 (bss)
int f2=0: 4468756 (bss)
static int f4: 4468776 (bss)
int f3=1: 4452352 (data)
static int f5=1: 4452356 (data)



Popular posts from this blog

JUnit – Run unit test in an Sequence / Order

In JUnit, we can use @FixMethodOrder( to run the test methods in a sequence or order.

import org.junit.FixMethodOrder;import org.junit.Test;import org.junit.runners.MethodSorters;importstatic;importstatic org.junit.Assert.assertThat;//Sorts by method name@FixMethodOrder(MethodSorters.NAME_ASCENDING)publicclassExecutionOrderTest{@TestpublicvoidtestB(){assertThat(1+1,is(2));}@Testpublicvoidtest1(){assertThat(1+1,is(2));}@TestpublicvoidtestA

Create Runnable Jar - Eclipse Options

When exporting to a Runnable Jar, there are three options in eclipse Helios. Extract required libraries into JARPackage required libraries into JARCopy required libraries into sub folder next to JAR. What are differences : Extract required libraries into JAR - Extracts the actual .class files from the libraries your app uses and puts those .class files inside the runnable JAR. So, the runnable JAR will not only contain the .class files of your application, but also the .class files of all the libraries your application uses. Package required libraries into JAR - Puts the actual JAR files of the libraries into your runnable JAR. Normally, a JAR file within a JAR file cannot be loaded by the JVM. But Eclipse adds special classes to the runnable JAR to make this possible. Copy required libraries into sub folder next to JAR - Keeps the library JARs completely separate from the runnable JAR, so the runnable JAR will only contain the .class files of your application. Option #2 is convenient be…