C++ Memory leak tests on a Windows Platform

In C++, unit tests are ideal for ensuring correct functionality. But how do you make sure you don’t have memory leaks in your code,  leaks that eventually cause your application to crash when it runs out of memory? Unit tests don’t typically run into memory problems directly because they tend to start up,  run a  small, self-contained piece of code, and shut down — getting a nice fresh memory environment on each test start.

Memory Leak Tests

One great way to help protect yourself from uptime problems is to write memory leak tests. These are unit tests where you first perform some operations, then do normal cleanup,  and finally you assert that the objects you were using during the operation have been cleaned up completely. In other words, that there are no objects left anywhere on the heap. To obtain this sort of information, we could override new/delete and malloc/free,  providing our own heap implementations that stores stack traces on allocation and produces a report when the heap is destroyed. This is a fair bit of work.

Memory Leak Tests on a Windows Platform

If you’re using Microsoft Visual C++ however, there is another solution available:

Microsoft’s Debug heap functions can be used to generate the report you want.
Unfortunately it may not be as automatic as you’d like.

Microsoft offers these low level functions:

_CrtSetReportMode
_CrtSetReportFile
_CrtMemCheckpoint
_CrtMemDumpStatistics
_CrtSetReportFile
_CrtSetDbgFlag

Some internal bookkeeping and filtering of the results is still necessary. Besides this, it is hard to filter out the relevant information.

MemLeakHound

Recently we wrote a utility  that keeps track of all the needed management.  MemLeakHound is designed to smoothly integrate with a unit testing framework such as GoogleTest. The principal design goal was to have the possibility to manually set the start and stop points for memory snapshots and leak detection. Integration of these calls in  the  setup and tear down methods is also possible. The  output of the memory leak issues are displayed as failed tests with detailed and meaningful information.

Here is a simple example with Google Test:

class Example1 : public testing::Test
{
public:
    void StartMemTracker(const CString& i_rstrName)
    {
        m_name = i_rstrName;
        MEMORY_LEAK_TRACKER_SETUP(m_name);
        MEMORY_SNAPSHOT_START(m_name);
    }

    void StopMemTracker()
    {
        MEMORY_SNAPSHOT_END(m_name);
        MEMORY_LEAK_TRACKER_TEARDOWN();
    }
private:
    CString m_name;
};

TEST_F(Example1, Leak1)
{
    StartMemTracker(_T("LeakTest1"));
    test1* test = new test1;
    // do something
    //...
    // oops, forgotten to clean up
    StopMemTracker();
};

The method StartMemTracker  takes a memory snapshot and starts the memory tracking facility. StopMemTracker takes a memory snapshot and stops the memory tracking.

The two snapshots are compared and a memory leak output is generated, if any differences were found. It displays the file and  line where memory was allocated.
When we run the example we get following output:

[ RUN      ] Example1.Leak1

Memory snapshot differences:
c:projectsmemleakhoundexamplesexamplesexamplesexample1.cpp(42)
[0x20f920] 4 bytes, Unique id: 1373
...
Memory Snapshot (LeakTest1) check failed...

[  FAILED  ] Example1.Leak1 (36 ms)

MemLeakHound works also with malloc, calloc and realloc:

TEST_F(Example1, Leak2)
{
    StartMemTracker(_T("LeakTest2"));
    char * buffer = (char*) malloc (10);
    StopMemTracker();
};

And the Google Test output:

[ RUN      ] Example1.Leak2

Memory snapshot differences:
c:projectsmemleakhoundexamplesexamplesexamplesexample1.cpp(52)
[0x34e418] 10 bytes, Unique id: 3735
...
Memory Snapshot (LeakTest2) check failed...

[  FAILED  ] Example1.Leak2 (34 ms)

Benefits

One Tool:

When writing unit tests in c++ you get the odd feeling that you missed something.  Did you forget any deletes or calls to free?  With this approach you run the leak tests and the unit tests at once.

Visibility in Continuous Integration Frameworks:

Today it is easy to integrate the results of a unit test with a continuous integration framework. Most Unit Test frameworks  generate a standard xunit output format which is understood by the continuous integration framework.

The coupling of MemLeakHound with Google Test  enables us to publish the leak issues in a continuous integration environment.

Limitations

Debug Mode:

MemLeakHound works only in debug mode. The leak detector is ignored if the unit tests are run in release mode.

Includes:

To enable the debug heap functions, a header file with following content has to be included in all of your C++ Files.

#ifdef _DEBUG
#include
#include
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#define new DEBUG_NEW
#endif

Third party libraries:

Memory Leaks in Third Party Libraries will not be tracked.

This entry was posted in C++ and tagged , , , . Bookmark the permalink.

One Response to C++ Memory leak tests on a Windows Platform

  1. Gunnar Skogsholm says:

    Where is this utility?

Leave a Reply

Your email address will not be published. Required fields are marked *