This simple standalone memory leak detector plugs right into your C++ project, and can be turned on by simply defining
DEBUG_MEMORY in your project's preprocessor setting or in your makefile, and calling
DumpUnfreed(TRUE); at the end of your program to create a memoryleak.txt file when your program exits. You can also call
DumpUnfreed() at strategic locations within your program. This code is very portable, and will run in any Windows, Linux, or DOS environment. It has also been tested in the Linux environment for the GCC 3.2.2 compiler and on Win32 using Developer Studio 1.1. The
DebugMemory routines override
new. The memoryleak.txt file prints out the file and line number and the file name where the allocation took place, as well as the address of the buffer allocated and its size. Any addresses that are freed through
DebugMemory that were not allocated through
DebugMemory are also noted in the memoryleak.txt output file.
In addition to creating a memory leak report, you can trace every allocation and deallocation in your code by placing a call to
DebugMemoryLogAllocations(TRUE); at the beginning of your program. This will create a file called debugmemorylog.txt that shows every allocation and deallocation that runs through the
DebugMemory interfaces. The additional logging does slow down your program significantly, so this feature is not suitable for real-time applications.
Using the Samples
Included in the zip are two additional zip files that have samples that test the various
free overrides. GCCSample.zip includes a Linux sample with a makefile, and Win32Sample.zip includes a Windows Developer Studio 1.1 sample project. The sample demonstrates allocating standard memory chunks through
calloc, and deallocating those chunks via
free. It also shows allocating a C++ class as a single object, and an array of class objects. The class constructor also allocates memory via
new, and deletes that memory in its destructor. In addition, it shows a derived class that instantiates the base class, plus the derived class allocates memory in its own constructor for members local to the derived class. The derived class is allocated as a single object and also as an array of objects in the sample code. You can walk through the allocations using the Visual Studio debugger and watch how the memory allocation system works.
The sample program source is identical for both operating systems, and produces a debugmemorylog.txt trace file of each allocation and deallocation, as well as a memoryleak.txt output file. The sample will show a total of 175 allocations and 175 deallocations, and no memory leaks.
However, if you uncomment out lines 126, and 127 in the main program, it will run both the standard lib and C++ allocation routines again, but not free the memory the second time through, and produce a detailed memory leak report in the memoryleak.txt file.
Using the code
To use the code in your project add DebugMemory.cpp and DebugMemory.h to your project or makefile. Define
DEBUG_MEMORY as a Preprocessor Definition for the compiler. Include DebugMemory.h in stdafx.h or in another .h file that gets included by all the code you want to debug. Add the routine
DumpUnfreed(TRUE); to your code just before your program exits. Compile and test.
Points of Interest
The breadcrumb trail of memory blocks used by
DebugMemory grows dynamically as needed by the utility, so you do not have to worry about setting some pre-defined size. The memory allocation for the list is not part of the
Note that C++ objects that are singleton, have static or global scope, and allocate memory in their constructors, will show as leaking when you call
DumpUnfreed() before you exit your program because their scalar destructors do not get called until the program is unloading as part of
If you choose to use this code for a compiler other than Microsoft VC++, Developer Studio, or GCC 3.2.2, you may need to change the prototypes that use the preprocessors
__LINE__ to replacements suitable for your compiler. However, the code should port easily in other compiler environments since it does not require anything other than standard C runtime library elements.