Memory leaks in C++ and how to avoid them by breakaleg


A memory leak is what happens when you forget to free a block of memory allocated with the new operator or when you make it impossible to do so. As a consequence your application may eventually run out of memory and may even cause the system to crash. I will now give you a few tips. Remember that code lines shown in red are the best alternative to each situation – they may be added or may even replace previous code.

  • Delete it before reallocating it

     

    char *string; string = new char[20]; delete [] string; string = new char[30]; delete [] string;

    So we have the new, we have the delete… where is the leakage ? Obviously we have two consecutive memory allocations via the string pointer, but something seems to be missing. We should have a delete [] statement right after the first allocation and then try to reallocate using a different size parameter. If we choose not to, the second allocation will assign a new address to the string pointer while the previous one will be lost. This makes it impossible to free the first dynamic variable further on in the code, resulting in a memory leakage.

  • Be sure you have a pointer to each dynamic variable. What do you think will happen at the end of this code fragment ?
char *first_string = new char[20];
char *second_string = new char[20];
strcpy(first_string, “leak”);
second_string = first_string;
strcpy(second_string, first_string);
delete [] second_string;

You guessed right, we have a memory leak here. What happened is that we have lost the address of the dynamic variable associated with second_string (as a side-effect of the pointer assignment) so we cannot delete it from the heap anymore. Thus the last line of code only frees the dynamic variable associated with first_string, which is not what we wanted.

The main idea is to try and not lose the addresses of dynamic variables as you may eventually not be able to free them.

  • Watch out for local pointers. Consider the next function :
void leak() {
int k;
char *cp = new char(‘E’);
delete cp;
}

Obviously both the k and cp variables are local so they are allocated on the stack segment. Then when it comes the time to exit the function they will be freed from memory as the stack is restored.

So what happens if we do not provide a delete cp statement ? Will the dynamic variable associated with the cp pointer also be erased from heap at function exit ? C++ has no mechanism to do this, we have to handle it ourselves by coding an explicit delete cp line.

  • Careful with functions returning dynamic variables

Let us take a look at the following program.

#include <iostream>char* tostring(int n) {
char *S = new char[100];
char aux;
int i, j;for (i = 0; n; n /= 10, ++i)
S[i] = n % 10 + ’0′;
for (j = 0; j < i / 2; ++j) {
aux = S[j];
S[j] = S[i - j - 1];
S[i - j - 1] = aux;
}
S[i] = ”;return S;
}void main() {
cout << tostring(23) << tostring(146) << endl;
    char *temp;
temp = tostring(23); cout << temp; delete [] temp;
temp = tostring(146); cout << temp; delete [] temp;
}

Obviously the function char* tostring(int n) converts the integer n to a string, but that is not of our interest right now. You may have noticed that the string stored in S is not freed from the heap before exiting the function. We have just been warned about local pointers though. The reason for this is that the string should also be available within the calling function main() as we need to print it out to screen. To solve this “contradiction” we should first assign the return value to a temporary pointer variable inside main(), print it out and be sure to delete [] it right away, as shown above.

You may ask yourself why use a supplementary pointer here, why not stick to the previous variant which is also more compact ? The answer is simple – we may not be able to delete [] the dynamic variable returned by the tostring() function call as its address would eventually be lost if we do not store it somewhere. For example the calls tostring(23), tostring(146) within the cout statement return two dynamic variables whose adresses are only used at printing, they are then lost. This leads to memory leakage.

  • Avoid these combinations : new – delete [] and new [] – delete

As stated above you should use the delete [] operator in order to free a heap-allocated array and prefer the delete variant to free a single object, otherwise the application may have an unexpected behaviour. The following are to be avoided :

int *vector = new int[10]; …
delete vector;
delete [] vector;
and
char *a = new char(‘A’);
delete [] a;
delete a;

 

  • Avoid these combinations : malloc() – delete and new – free()

    char *a = (char*) malloc(10);

    delete [] a;
    free(a);
    orchar *b = new char[10];

    free(b);
    delete [] b;

My advice is not to mix C with C++ as they have different approaches to dynamic memory allocation. Make up your mind and choose either of them, or your application may run erratically. I personally recommend the C++ new and delete operators.