Navigation Bar

28 October 2011

[C++] - Memory Segmentation in C++

Introduction - Memory Segments


In the previous article, we saw about the pointer and reference variables in the context of stack memory. There are 3 more important memories that every c++ programmer should be aware of it. Below is the four important memory segmentation:


  1. Stack Memory Segments
  2. Heap Memory Segments
  3. Code Segmentation
  4. Data Segmentation

In this article, we will have a look at these memory segments with a simple example. The example is just for understanding the purpose and it does nothing actually excepting printing something.

Memory Segments - An example


The complete example is shown below:

// CPPTST.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>

//MemSeg01: Declare a Global Variable
int x = 10;

//MemSeg02: Store address of the Global variable in a Global Pointer
int* px = &x;

//MemSeg03:  Function definition. Takes a number and prints it
void PrintNo(int x)
{
            int y;
            y = x;
            printf("The given number is %d", x);
}


int _tmain(int argc, _TCHAR* argv[])
{
            //MemSeg04: Declare a loval variable and declare a pointer and store the address of local variable
            int m = 12;
            int* pm = &m;

            //MemSeg05: Local pointer storing the Global Address
            int* pgx = &x;

            //MemSeg06: Local pointer storing the heap address and assigning a value to the heap
            int *pInt = new int;
            *pInt = 22;

            //MemSeg07: Local pointer to a function that returns void and takes int
            void (*pFun)(int);

            //MemSeg08: Pointer storing the base address of the function
            pFun = &PrintNo;

            //MemSeg09: Calling the function through function pointer
            pFun(117);
           

            return 0;
}

Let us explore the example in terms of the memory segmentations.

Code Memory Segment


Well. The code is displayed above. What will you do with it? The first thing is compiling it and then linking the code. Let use assume that the above code is placed in the MyProgram.CPP file. When you compile, the compiler will translate this human readable language into something that called as object code. If there are 20 such files, the job of the compiler is to generate twenty different object files and prompt any errors that do not comply to the C++ syntax. Then the linker will go through all 20-object files to form an executable that is the .exe file.

What happens when you double click the exe name? The exe is considered as a process by the operating system and once the process is committed, the M/c code (exe) is loaded into the memory and processor will access these machine instructions to perform specified action. This memory is called Code Segment. In out example, the translated code goes as exe, and when the exe is executed, the instructions are loaded into the memory called code segment.

Let us take the first statement in the Program entry:
            //MemSeg04: Declare a local variable and declare a pointer and store the address of local variable
            int m = 12;

The above code will be translated and packed in the exe as a machine-readable language. In the VS2005 IDE, I kept a breakpoint on the above-shown statement and once the breakpoint is hit, using the context menu I asked for show Assembly code. The Assembly revealed is shown below:




The address marked in Red box shows it stores the assembly command MOV (It may be mapped to number and then in terms of zeros and ones that is low and high voltage. We no need to go that much deep into the electronics of it). The Address in the Red box is actually allocated in the Code Segment. A pointer can store this address also.

Data Memory Segment


As the name implies it is the segment for application data. Do you heard your senior asking multiple questions when you declare a global variable? He asks, because the global variables go and sit in the data segment of the memory. So what? If it sits there, it lives until the program dies and there is no ways to say get lost. Think about a big project and 1000 of people worked on it (Even in maintenance) for last 10 to 20 years declared plenty of global variables even when it is avoidable by alternate techniques. When the program loads (in Code segment) it needs to allocate space for all those variables and allocated space is never cleared until the program exits. That is why we call these global variables and constants are application data. The memories associated to these global are known as data segment memory and it will get cleared when the program is removed.

In our example the following two statements are occupying the memory in the data segment.

//MemSeg01: Declare a Global Variable
int x = 10;

//MemSeg02: Store address of the Global variable in a Global Pointer
int* px = &x;

Note that the pointer px is holdling the address of some data segment memory allocated to variable integer x. Also, the space required for holding that address also allocated in the data segment. Here, the value in the px, x can be changed. But, the space allocated for it cannot be washed out.

Heap Memory Segment


Allocating and clearing the memory in the memory segment for Stack, Code and data is taken care by the system. But, heap memory is given in the hands of C++ programmer. They can create byes of memory as well as clear it whenever they want.  So the programmer determines the lifetime of the memory allocated. Consider the statement below taken from the example:

            //MemSeg06: Local pointer storing the heap address and assigning a value to the heap
            int *pInt = new int;
            *pInt = 22;

In the above statements, space required to store an integer value is allocated in the heap. The allocated address is stored in the variable pInt. The variable pInt is inside the main function and so the space for variable pInt is allocated in the stack holding address in the heap (Enough to store an integer).  So when we go out of the function all the stack memory associated to it is cleared. But, the allocated heap becomes un attended or blocked stating in use. Because system will not clear it and programmer should do that. To clear that heap, before you lose the address in the stack for pInt, you should use the statement delete pInt.

What happens if the above two statements are next to the comment MemSeg01 that is not inside any of the function? Well. Heap memory is stored in data segment variable pInt.

Stack Memory Segment


It is the memory segment where almost everybody declares and uses the variables. When you declare a variable inside the function that goes to the stack segment of the memory. All the stack segments wiped out once you go out of the function and when you come inside the some other function a new stack segment for that function is created. So this is a less costly segment as it lives till corresponding function returns back to the caller.
Let us assume Program main calls the function A. Here first the Stack Segment for Main is created, then when you are inside the function A, main programs stack segment becomes un-accessible and at the same time stack segment for Function A is created. When the function A return the control to main program, stack segment for A is cleared and stack segment for program main (Still lives, it became temporarily un-accessible) becomes available. You can refer my previous post for detailed example about stack segment.

In our example the below two statements in the main is created in stack segment:
            //MemSeg04: Declare a loval variable and declare a pointer and store the address of local variable
            int m = 12;
            int* pm = &m;

Before we close


Below is the Illustration of memory segment and variable involved in our sample.




We know that a pointer can hold an address. In our example,

Pm – is holding the address of memory in stack segment
Pgx – is holding the address of the memory in the data segment
Pint – is holding the address of the memory in the heap segment
PFun – is holding the address of the memory (Starting address or base address of the void PrintNo(int x) ) in the code segment.

Pfun?

That is function pointer, I will write about it later. There is a nice movie in HBO, I will spend sometime there.



13 October 2011

[C++] - Reference vs Pointers

Introduction - Reference and Pointers


A pointer is a notation that says it points to something. In C++ or C that something is known as an address. The next question, what is address? Hey, Rachel! Where do you stay? She will give her address to her new friend so that he can locate her living place. The context is same in c++ also. Every value stored by your program will occupy some memory location.

Here we will see some basics of what are pointer variable, reference variable, and a normal variable.

A simple pointer and reference to a variable


A variable is declared as follows:
int                    x;

Here,
X is the variable name
int specified the type of data that can be stored in x.

Let us assume that the variable shown above is declared in the void main of the program. The variable scope is inside the main and we know that the variable occupies some memory in the call stack of main. Now the x is a naming given to the location in the stack that is allocated by the void main function. Using the assignment operator and the variable x the location is accessed. So the address involved is hidden behind the scene and all you know is variable name x and internally is has an association to a location in the stack memory of the main function.

Now have a look at the variable declaration below:
int&      refto_x  = x;

Here,
refto_x is reference variable and that references the variable x. Int& specifies the reference notation and reference to what data type.

The reference variable should be initialized when it is declared. See… in our example statement we declared a reference variable refto_x and initialized it with the assignment = x. What does that say? Well. X is a naming notation used internally to read or write from a specific memory location in a stack (When x is not a global variable and declared inside some function) and simply it is a variable declared already. And refto_x is a naming notation for the naming x. That means refto_x is simply one more naming given to the location represented by the variable x.

Now look at the statement below:
int * pointerto_x = &x;

Here,
int * - Represents pointer to an integer
pointerto_x – A variable name given to the pointer variable
&x – Address of the variable x.

In the above declaration, a pointer variable pointerto_x is declared and at the same time initialized to have the address of the variable x. Note that in the above statement unlike reference it is not just one more name to the location represented by x. It has it own location represented by a variable pointerto_x and that location can store address location and when it access that location it treats that address location to read or write integer sized data.

Basic explanation for reference and pointers


Let us explore the pointer, reference and a normal variable with an example. Consider the below four statements:
int _tmain(int argc, _TCHAR* argv[])
{
//Declare an integer variable, then have a pointer and reference to it
int                     x;
int&       refto_x  = x;
int * pointerto_x = &x;
x = 10;
}

First, we declared an integer variable x and then had a reference to it in the variable refto_x. Then the pointer variable pointerto_x is declared and initialized to hold the address of the variable x. Finally, we assigned value 10 to the variable x. Have a look at the below picture:



The above three variable creation and assignment of value 10 is depicted as above. First, to store the value 10 we need some bits in memory. Second as the variable x is declared inside the _tmain () function and value 10 is assigned to the variable x, memory in the stack holds the value 10.  To read or write from this memory location we use the variable x.

Read:
p = x + 15;
In the above statement, the value in the stack memory identified by the variable x is read then assigned to variable p after summing it with a value 15.

Write:
x = p - 10;
In the above statement the value in p is decremented by 10 then written to the memory location identified by the variable x.

So, according to x, the read or write operation defined by the variable x and it position in relation to the assignment operator =. C++ developers call the variable name and its corresponding memory location as naming association.

Now explaining the reference is easy. In our example statements above, refto_x is just one more naming association to the same stack memory. That means x and refto_x both corresponds to the same memory in the stack. What about pointerto_x? It stores the address of the memory location for x or refto_x.

The above four statements can further explained in detail by using the below depiction:



1.      FE100B12: Memory address of stack that holds value 10
2.      FF820CD7: Again, memory address of stack that holds address of some other memory in stack (32 bit address or 64 bit address)
3.      Variable x is associated to the memory location FE100B12
4.      Variable refto_x is also associated to the memory location FE100B12
5.      Variable pointerto_x is associated to the memory location FF820CD7

Note that x, refto_x and pointerto_x all declared inside the main () and have an association to the stack memory. I will talk about heap later and that is different.

The value in the location is shown above. If you just read the content of the pointer variable pointerto_x, then you will get memory location of the variable. To read the content, you should de-reference the pointer.

int m = * pointerto_x;

In the above statement we specifed that we do not want the content of pointerto_x (Which is an address), But we want the actual value in the address which stored in the pointerto_x.

Code and Example


Below is the complete example and output:

#include "stdafx.h"
#include <conio.h>



int _tmain(int argc, _TCHAR* argv[])
{

            //Declare an integer variable, then have a pointer and reference to it
            int                     x;
            int&       refto_x  = x;
            int * pointerto_x = &x;

            //Assing a value to x and print the value in it using value, refernce and pointer
            x = 10;
            printf("X=%d\n", x);
            printf("Value in x through refto_x=%d\n", refto_x);
            printf("Value in x tnrough pointerto_x=%d\n", *pointerto_x );

            //Now check the address of all the three variables
            printf("********* Adress of Value, reference, pointer variables *********\n");
            printf("Address of x=%d\n", &x);
            printf("Address of refto_x=%d\n", &refto_x);
            printf("Address of pointerto_x=%d\n", &pointerto_x );
           
            //Special case
            printf("Then what is stored in pointerto_x? It is %d, address of x", pointerto_x);

            getch();
            return 0;
}

Output