Sunday, 23 November 2014

Common mistakes while dealing with the heap memory in C++


What are the common mistakes while dealing with the heap memory in C++?

Most programmers do the mistakes while dealing with the pointers and references; if we misuse them, they will eat our time and mind.
Here some of the possible mistakes done by developer while doing the code using pointers:

Null dereferencing:

When we try to use the NULL pointers and trying to do some operations on that. See the below example, here the application gets crashed because we are trying to access the NULL dereferencing.
using namespace std;
/*This is my base class */
class MyBaseClass
{
  int i;
       public:
          MyBaseClass();
          virtual ~MyBaseClass();
          void MyFun ();
};
MyBaseClass::MyBaseClass ()
{
   i = 10;
   cout << "Constructor of MyBaseClass" << endl;
}
void MyBaseClass::MyFun ()
{
   cout << "I am in the Function" << i << endl;
}
MyBaseClass::~MyBaseClass ()
{
   cout << "Destructor of MyBaseClass" << endl;
}
int _tmain (int argc, _TCHAR* argv[])
{
 MyBaseClass *pcPtr = NULL;
  pcPtr->MyFun ();
    getchar ();
    return 0;
}

Accessing invalid memory:

when we are trying to access the invalid memory location that is already deleted or the memory location that is not allocated.
int _tmain (int argc, _TCHAR* argv[])
{
  MyBaseClass *pcPtr = new MyBaseClass;
  delete pcPtr; pcPtr = NULL;
  pcPtr->MyFun (); // trying to accessing memory location that is already deleted
    getchar ();
    return 0;
}

Double Freeing:

When we try to free/delete the heap memory location that is already deleted.
using namespace std;
/*This is my base class */
class MyBaseClass
{
  int i; char *pcchtest;
       public:
          MyBaseClass();
          virtual ~MyBaseClass();
          void MyFun ();
};
MyBaseClass::MyBaseClass ()
{
   i = 10; pcchtest = new char [10]; pcchtest = _strdup ("Test");
   cout << "Constructor of MyBaseClass" << endl;
}
void MyBaseClass::MyFun ()
{
   cout << "I am in the Function" << pcchtest << i << endl;
}
MyBaseClass::~MyBaseClass ()
{
   cout << "Destructor of MyBaseClass" << endl;
   delete [] pcchtest; pcchtest = NULL;
}
int _tmain (int argc, _TCHAR* argv[])
{
  MyBaseClass *pcPtr = new MyBaseClass;
  pcPtr->MyFun ();
  delete pcPtr; pcPtr = NULL;
 delete pcPtr; pcPtr = NULL;
    getchar ();
   return 0;
}

The output of the above program is
Detected memory leaks!
Dumping objects ->
{158} normal block at 0x04A23770, 10 bytes long.
 Data: <          > CD CD CD CD CD CD CD CD CD CD
Object dump complete.
Mixing new & malloc / delete & free allocators:

Using delete to free memory that was allocated with malloc() or using free() to return memory allocated with new.
Let us see the below code
using namespace std;
/*This is my base class */
class MyBaseClass
{
  int i; char *pcchtest;
       public:
          MyBaseClass();
          virtual ~MyBaseClass();
          void MyFun ();
};
MyBaseClass::MyBaseClass ()
{
   i = 10; pcchtest = new char [10]; pcchtest = _strdup ("Test");
   cout << "Constructor of MyBaseClass" << endl;
}
void MyBaseClass::MyFun ()
{
   cout << "I am in the Function" << pcchtest << i << endl;
}
MyBaseClass::~MyBaseClass ()
{
   cout << "Destructor of MyBaseClass" << endl;
   free (pcchtest); pcchtest = NULL;
}
int _tmain (int argc, _TCHAR* argv[])
{
  MyBaseClass *pcPtr = new MyBaseClass;
  pcPtr->MyFun ();
  free (pcPtr); pcPtr = NULL;
    getchar ();
    return 0;
}
Observe the output:
The program '[4580] TestCPP.exe: Native' has exited with code -1 (0xffffffff).
The program '[4580] TestCPP.exe: Managed (v4.0.30319)' has exited with code -1 (0xffffffff).


Incorrect array De-allocation:

When we allocate the array of memory, need to delete it using delete[], then only the memory gets deleted correctly
See the code sample below:
using namespace std;
/*This is my base class */
class MyBaseClass
{
  int i; char *pcchtest;
       public:
          MyBaseClass();
          virtual ~MyBaseClass();
          void MyFun ();
};
MyBaseClass::MyBaseClass ()
{
   i = 10; pcchtest = new char [10]; pcchtest = _strdup ("Test");
   cout << "Constructor of MyBaseClass" << endl;
}
void MyBaseClass::MyFun ()
{
   cout << "I am in the Function" << pcchtest << i << endl;
}
MyBaseClass::~MyBaseClass ()
{
   cout << "Destructor of MyBaseClass" << endl;
   delete (pcchtest); pcchtest = NULL;  
}
int _tmain (int argc, _TCHAR* argv[])
{
  MyBaseClass *pcPtr = new MyBaseClass;
  pcPtr->MyFun ();
delete pcPtr; pcPtr = NULL;
    getchar ();
    return 0;
}

The ouput of the above program is:
Detected memory leaks!
Dumping objects ->
{158} normal block at 0x0501FFC8, 10 bytes long.
 Data: <          > CD CD CD CD CD CD CD CD CD CD
Object dump complete.
The program '[6816] TestCPP.exe: Native' has exited with code -1073741510 (0xc000013a).
The program '[6816] TestCPP.exe: Managed (v4.0.30319)' has exited with code -1073741510 (0xc000013a).

The memory leaks is for the statement:
  delete (pcchtest); pcchtest = NULL;
  delete [] pcchtest; pcchtest = NULL;

Memory leaks, forgetting to free the allocated memory:

forgot to free the allocated memory. If it is small there is no effect for the performance of the application, if the allocated memnory is large the application gets crashed and the performance degrades.
int _tmain (int argc, _TCHAR* argv[])
{
  MyBaseClass *pcPtr = new MyBaseClass;
  pcPtr->MyFun ();
    getchar ();
    return 0;
}
The memory leak we can found as shown below
 
The program '[5864] TestCPP.exe: Native' has exited with code -1 (0xffffffff).
The program '[5864] TestCPP.exe: Managed (v4.0.30319)' has exited with code -1 (0xffffffff).

These types of problems we can reduce by implementing the smart pointers. Please follow Smart pointers implementation in the following link here on the same blog.

Smart pointers implementation in Cpp with examples.

No comments: