Tuesday, August 3, 2010

Common Pitfall : While using malloc instead of new.

Two mostly used things that help in allocating memory are malloc and new.

Sometimes knowledge of using malloc, for allocating memory in common and less complicated situations, can prove wrong in complicated situations.

Situation [1] (Complication Level 1):
int *pData = (int*)malloc(10 * sizeof(int));
Now to access integers at index from 0 to 9 simply use pData[1] or *(pData+2)...
Very simple!!!

Situation [2] (Complication Level 2):
struct ABC
{
int P1;
char P2;
};
ABC *pData = (ABC*)malloc(10 * sizeof(ABC));

Now to access integer P1 of say 4th struct ABC : pData[3].P1
Again Very simple!!!

Situation [3] (Complication Level 3):
struct ABC
{
int P1;
char P2;
};

struct PQR
{
int P1;
char P2;
ABC P3;
};
PQR *pData = (PQR*)malloc(10 * sizeof(PQR));

Now to access integer P1 of ABC which is inside of say 5th struct PQR : pData[4].P3.P1
Again Moderately simple!!!

In above 3 situations memory was allocated and then utilized according to the structure\ layout of structs.

Situation [4] (Complication Level 4):
struct XYZ
{
int P1;
char P2;
CList P3;
};
XYZ *pData = (XYZ*)malloc(10 * sizeof(XYZ));

Now try to insert elements in the list P3 of say 4th struct XYZ:
pData[3].P3.AddTail(2);
Complie Status OK.
Run Status CRASH!!!
Without reading further think a minute why the code did not worked even though memory was already allocated?

This happened because though memory was allocated for all the data members of list XYZ::P3 but those data members were not initialized with default values.

struct XYZ in above example is composite data type (a class or user defined data type) in which the default value initialization of its data-members is normally done in constructor of the class.

In a composite data type the data-members are created (here created means calling of their respective constructor) prior to the invocation of composite data type constructor itself. ("Refer how Object creation takes place")

So what will initialize the data-members along with the task of allocating the memory for members.
Answer : operator new

XYZ *pData = new XYZ[10];
Here 'new' invokes the constructor of both, the data members of struct XYZ and the struct XYZ itself. Inside the CList constructor, members can be initialized with default values.




Conclusion:
[1]Anyway, in C++ new is the preferred mechanism for memory allocation.
[2]Also try to minimize mixing of malloc and new.