Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find memory leak in a C++ code/project?

Instructions

Things You'll Need

  • Proficiency in C++
  • C++ compiler
  • Debugger and other investigative software tools

1

Understand the operator basics. 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 you allocated:

char* str = new char [30]; // Allocate 30 bytes to house a string.

delete [] str; // Clear those 30 bytes and make str point nowhere.

2

Reallocate memory only if you've deleted. In the code below, str acquires a new address with the second allocation. The first address is lost irretrievably, and so are the 30 bytes that it pointed to. Now they're impossible to free, and you have a memory leak:

char* str = new char [30]; // Give str a memory address.

// delete [] str; // Remove the first comment marking in this line to correct.

str = new char [60]; /* Give str another memory address with
                                                    the first one gone forever.*/

delete [] str; // This deletes the 60 bytes, not just the first 30.

3

Watch those pointer assignments. 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. Again, this results in a memory leak:

char* str1 = new char [30];

char* str2 = new char [40];

strcpy(str1, "Memory leak");

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

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

delete [] str1; // Possible access violation. What a disaster!

4

Be careful with local pointers. A pointer you declare in a function is allocated on the stack, but the dynamic variable it points to is allocated on the heap. If you don't delete it, it will persist after the program exits from the function:

void Leak(int x){

char* p = new char [x];

// delete [] p; // Remove the first comment marking to correct.

}

5

Pay attention to the square braces after "delete." Use delete by itself to free a single object. Use delete [] with square brackets to free a heap array. Don't do something like this:

char* one = new char;

delete [] one; // Wrong

char* many = new char [30];

delete many; // Wrong!

6

If the leak yet allowed - I'm usually seeking it with deleaker (check it here: http://deleaker.com).


You can use some techniques in your code to detect memory leak. The most common and most easy way to detect is, define a macro say, DEBUG_NEW and use it, along with predefined macros like __FILE__ and __LINE__ to locate the memory leak in your code. These predefined macros tell you the file and line number of memory leaks.

DEBUG_NEW is just a MACRO which is usually defined as:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

So that wherever you use new, it also can keep track of the file and line number which could be used to locate memory leak in your program.

And __FILE__, __LINE__ are predefined macros which evaluate to the filename and line number respectively where you use them!

Read the following article which explains the technique of using DEBUG_NEW with other interesting macros, very beautifully:

A Cross-Platform Memory Leak Detector


From Wikpedia,

Debug_new refers to a technique in C++ to overload and/or redefine operator new and operator delete in order to intercept the memory allocation and deallocation calls, and thus debug a program for memory usage. It often involves defining a macro named DEBUG_NEW, and makes new become something like new(_FILE_, _LINE_) to record the file/line information on allocation. Microsoft Visual C++ uses this technique in its Microsoft Foundation Classes. There are some ways to extend this method to avoid using macro redefinition while still able to display the file/line information on some platforms. There are many inherent limitations to this method. It applies only to C++, and cannot catch memory leaks by C functions like malloc. However, it can be very simple to use and also very fast, when compared to some more complete memory debugger solutions.


Running "Valgrind" can:

1) Help Identify Memory Leaks - show you how many memory leaks you have, and point out to the lines in the code where the leaked memory was allocated.

2) Point out wrong attempts to free memory (e.g. improper call of delete)

Instructions for using "Valgrind"

1) Get valgrind here.

2) Compile your code with -g flag

3) In your shell run:

valgrind --leak-check=yes myprog arg1 arg2

Where "myprog" is your compiled program and arg1, arg2 your programme's arguments.

4) The result is a list of calls to malloc/new that did not have subsequent calls to free delete.

For example:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)

==4230==    by 0x804990F: main (example.c:6)

Tells you in which line the malloc (that was not freed) was called.

As Pointed out by others, make sure that for every new/malloc call, you have a subsequent delete/free call.


There are some well-known programming techniques that will help you to minimize the risk of getting memory leaks at first hand:

  • if you have to do your own dynamic memory allocation, write new and delete always pairwise, and make sure the allocation/deallocation code is called pairwise
  • avoid dynamic memory allocation if you can. For example, use vector<T> t whereever possible instead of T* t = new T[size]
  • use "smart pointers" like boost smart pointers (http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
  • my personal favorite: make sure you have understood the concept of ownership of a pointer, and make sure that everywhere where you use pointers, you know which code entity is the owner
  • learn which constructors / assignment operators are automatically created by the C++ compiler, and what that means if you have class that owns a pointer (or what that means if you have a class that contains a pointer to an object it does not own).

Valgrind http://valgrind.org/

and

GDB http://www.gnu.org/software/gdb/


  1. Download Debugging Tools for Windows.
  2. Use the gflags utility to turn on user-mode stack traces.
  3. Use UMDH to take multiple snapshots of your program's memory. Take a snapshot before memory gets allocated, and take a second snapshot after a point at which you believe that your program has leaked memory. You might want to add pauses or prompts in your program to give you a chance to run UMDH and take the snapshots.
  4. Run UMDH again, this time in its mode that does a diff between the two snapshots. It will then generate a report containing the call stacks of suspected memory leaks.
  5. Restore your previous gflags settings when you're done.

UMDH will give you more information than the CRT debug heap because it is watching memory allocations across your entire process; it can even tell you if third-party components are leaking.