Introduction
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 malloc()
, calloc()
, free()
, delete()
, new()
, delete[]
, and 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 new
/ delete
, malloc
, calloc
, and 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 malloc
, 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.
DumpUnfreed(TRUE);
exit(0);
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 DebugMemory
trace.
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 exit(0)
.
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 __cdecl
, __FILE__
and __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.