Advanced Memory Management: Dynamic Allocation, Part 1By Andrei Milea
malloc and free, new and deleteDynamic allocation is one of the three ways of using memory provided by the C/C++ standard. To accomplish this in C the malloc function is used and the new keyword is used for C++. Both of them perform an allocation of a contiguous block of memory, malloc taking the size as parameter:
int *data = new int; int *data = (int*) malloc(sizeof(int)); //notice the use of sizeof for portability
This memory block can be used whenever needed during the program execution or until explicitly deallocating it, unlike the automatic memory which is available only inside the function or block of instructions where it was declared. Allowing a program to allocate dynamic storage every time it needs more until the program stops can cause it eventually to run out of available space. To prevent this behavior C++ provides the delete operator with the job of recycling a segment of memory allocated with new:
delete (data);The C function for memory deallocation is free() and has the same behavior as delete, it frees the space pointed by data for future use:
free(data);If the allocated memory is not freed when it's no longer necessary it will result in a memory leak. It is not specified what will happen to the leaked memory, but contemporary operating systems collect it when the program terminates. Memory leaks can be very dangerous because the system may run out of memory. To eliminate them, C++ provides a destructor member for every class where the programmer should deallocate all the memory it allocates inside the class. In other languages like Java or C# a garbage collector is used that figures out which memory blocks are no longer needed and deletes them, taking the burden of deallocation from the programmer's shoulders, but adding some overhead in runtime. In C++, you can use smart pointers that hold on to a piece of memory and deallocate that memory in their destructors.
Even though malloc and free are available in C++, their use is not recommended; it is always preferred to use new and delete, especially when working with objects. Also, notice the cast to int in the malloc allocation. This is not required in C because the C standard allows implicit cast between void *, which is the type returned by malloc, and other pointer types. In fact, in C, casting malloc is considered undesirable. But if we want to use malloc in C++ code we must explicitly cast the pointer returned by malloc to the appropriate type. Actually the use of void* pointers in C++ is not recommended because it can break multiple inheritance, that is, in a multiple inheritance hierarchy some of the classes can view different values of the this pointer (the original value with some offset) and casting to void* can break the protection mechanisms of C++. If a void* cast is needed in this situation it is recommended to use a dynamic_cast or static_cast as soon as possible, to adjust the this pointer automatically.
The backward portability with malloc and free is useful in C++ for supporting legacy C code and to allow implementing (overloading) the new and delete operators using calls to malloc/free. Because the operator new does more than just allocating memory (it also calls the object's constructor), it is not allowed to use free for data allocated with new or vice versa (delete with malloc).
The advantages of using new and delete over their older relatives malloc/free are the following:
In some cases throwing an exception is not desirable (probably for working with legacy codebases that do not expect or handle exceptions, and also perhaps to avoid the overhead of supporting exceptions). For this situation the standard provides an exception-free version of new and new:
void* operator new(std::size_t size, const std::nothrow_t&) throw(); void* operator new(std::size_t size, const std::nothrow_t&) throw();Dynamic memory can be used not only to store data for your application; you can use it for functions too. A pointer that points to a function (function pointer) can be declared like this:
int (*f)(int,int); //this is a pointer to a function taking 2 ints as arguments and returning one f = &pow; //now function pow can be called using the pointer fEven if in C++ you have other means to avoid the using of function pointers, the new operator can be used to allocate memory for a pointer to a function:
int (**f)(int,int) = new (int (*) (int,int));The above line can be quite confusing for people not used with function pointers. In order to get a better view on them, see the function pointers tutorial.
Dynamic arraysCreating a dynamic object is different than creating an array of objects and C++ handles the two situations differently. The new and delete operators are used for creation of dynamic instances of classes or built-in types, while new and delete create and destroy dynamic arrays.
Myclass *my_class; my_class = new Myclass [size]; //size must be of type int //do work with my_class delete  my_class;The call to new  in the above example allocates memory for the entire array and then calls the default constructor for every object in the array in an increasing order. The returned value is a pointer to the beginning of the allocated storage, the first element in the array. In the end, the delete  operator calls the destructor for each object in reversed order and then deallocates the memory.
There are two limitations in creating a dynamic array of objects. One of them is that you can't create a multidimensional array explicitly, like for automatic (stack-based) arrays:
Myclass **my_class; my_class = new Myclass[size1][size2]; //this will yield a compilation errorIt is a consequence of the way the memory is allocated, in fact the storage for a multidimensional array is not contiguous; each element contains a pointer to another array.
In order to obtain a 2-dimensional array you can do something similar with this:
my_class = new Myclass* [size1]; //note that the type is a Myclass pointer for(int i=0; i<size1; i++) my_class[i] = new Myclass [size2];To deleted the allocated memory you must go through the first array and apply delete to every element and then delete the main one:
for(int i=0; i<size; i++) delete  my_class[i]; delete my_class;The above methods can easily be generalized to obtain and destroy an n-dimensional array.
The other important restriction is that the explicit initialization is banned, so you can't pass parameters when building an array of objects with new; only the default constructor gets called.
Dynamic Memory Allocation, Part 2: Dynamic Memory Allocation and Virtual Memory
Dynamic Memory Allocation, Part 3: Customized Allocators with Operator New and Operator Delete
Dynamic Memory Allocation, Part 4: Common Memory Management Problems in C++
Using auto_ptr to avoid memory leaks.
Finding memory leaks with Valgrind