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

Leave a comment