Memory leaks, system tweaks & C++ operator heaps


This is a guest post by Alex Guryeva, a test consultant with SQS Software Quality Systems.


Imagine that you are a company director and you’re a bit of an entrepreneur. One week you get the call you’ve been waiting for and you receive the venture capital funding that you need to get your business moving. Unfortunately though, after the specified period of time, you are unable to return the money to the bank for one reason or another. In this case, we can define our ‘leak‘ as the loss, experienced by the bank, of the resources that were allocated (i.e. the money).


In computing terms, a memory leak occurs when a computer program consumes memory resources but is unable to release that memory back to the operating system.


Memory leak bugs usually kill your system slowly and painfully. After a fresh boot, which is a part of the development or testing process, everything looks ok and the system appears to work fine — and because of this it’s hard to notice memory leaks during unit-tests or lab tests.  


Depending on the total amount of RAM and the extent of the memory leak, the system will continue to run and perform well for a certain amount of time (hours, days or even weeks) and during this time, the amount of free memory is steadily decreasing.


A memory leak is a common error when using languages that have no built-in automatic garbage collection such as C and C++ (you can think of garbage collection as kind of automated debt recovery system). To prevent memory leaks you need to be conscientious with your use of the “new” and “delete” C++ operators. The C++ operator “new” allocates heap memory. The “delete” operator frees heap memory. For every “new,” you should use a “delete” so that you free the same memory that you allocated.


Example A: Delete it before reallocating


char *string;

string = new char[20]; // first allocation

string = new char[30]; // second allocation

delete [] string;


In this example we should have a delete [] statement right after the first allocation and then try to reallocate using a different size parameter. If we don’t, 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 memory allocated for the first dynamic variable further on in the code, resulting in a memory leak.


Example B: Watch the pointer assignments


char* str1 = new char [30];

char* str2 = new char [40];

strcpy(str1, “Memory leak”);

str2 = str1;     // Now the 40 bytes are impossible to free

delete [] str2; // This deletes the 30 bytes

delete [] str1; // Possible access violation


Every dynamic variable (allocated memory on the heap) needs to be associated with a pointer. When a dynamic variable becomes disassociated from its pointer(s), it becomes impossible to erase and this results in a memory leak.


Also, memory may leak despite the presence of a garbage collector. Garbage collection in the Java programming language simplifies memory management and eliminates most common memory problems. However, contrary to popular belief, garbage collection cannot take care of all memory problems. Difficult to detect Java memory leaks include leaks that result from design and implementation errors (for example, a reference to an object kept beyond its useful life). This kind of leak is also described as a logical memory leak.


Tips & Warnings:


•     Make sure all memory allocations are coupled with memory free

•     Cover all “if-else”, “switch-case” and other conditional flows, including erroneous flows, to make sure that the coupling still remains

•     Make sure that a pointer that holds an address to dynamically allocated memory is not erased or overrun by another value. If this happens, you will not be able to free the resource

•     Consider using debugging tools for C/C++ to detect unreachable memory, for example IBM Rational Purify, BoundsChecker, Valgrind, Insure++

•     Consider using memory-profiling tools such as OptimizeIt, JProbe, or JInsight