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

Exploring Node.js Internals

I found a great article explaining Node JS internals, must read : Some other articles : Introduction to Node.js Being an official website, explains what Node.js is, as well as its package managers, and lists web frameworks built on top of it. “ JavaScript & Node.js ”,  The Node Beginner Book This book by  Manuel Kiessling  does a fantastic job of explaining Node.js, after warning that JavaScript in the browser is not the same as the one in Node.js, even though both are written in the same language. Beginning Node.js This beginner book goes beyond an explanation of the runtime. It teaches about packages and streams and creating a web server with the Express framework. LibUV This is the official documentation of the supporting C++ code of the Node.js runtime. V8 This is the official documentation of the JavaScript engine that makes it possible to write Node.js with JavaScript.

Hibernate Object Conversations

Session methods to use for object conversations Save() A new instance being attached to the session. An insert will be scheduled. Update() Call Update to make a transient object persistent again. It will force a SQL update on the transient object. This is because Hibernate does not know whether the object is dirty or not and to be safe by default schedules an update. This method will throw an exception, if the entity is already registered with the session. - NonUniqueObjectException is thrown. saveOrUpdate() Either a save or an update will be called based on whether the identifier exists or not. No identifier - save is called, else update is called. Or for a better understanding, if the object is transient, then a save is called, if the object is persistent, then an update is called. Reattaching an unmodified instance - If you know for sure that an object is not modified and you just want to make it persistent again - Session.lock(item, LockMode.No