Visual Studio has the ability to report memory leaks after running an application in debugging mode. This is generelly somehow satisfactory, but raises some problems when developing a Qt application. Qt allocates memory in it’s DLLs and this memory is released when the DLLs are unloaded. Unfortunately this is after Visual Studio reports the supposed leaks.
I’m not sure if this happens always or only in applications that link against MFC libraries. I read somewhere that the MFC cleanup code triggers the check and that this is unfortunately before 3rd patry DLLs can do their cleanup. Thus, the check falsely reports memory leaks.
In case of my application (WinFIG) about 1600 leaks are reported, although none of them is real. This has two annoying implications:
- Ending the debugger is delayed until the dump is complete
- It gets very hard to find the real memory leaks
Ok, so far so bad, but what to do? There is a way to replace the function that actually writes the leak info to the output console. I managed to replace this by a function that filters everything out that is not originated from my own code. To sort out, which leaks are from my code and which are from somewhere else, I need to mark “my” memory leaks. I do this with the following definition.
setDebugNew.h
#if defined(WIN32) && defined(_DEBUG) #define new DEBUG_NEW #endif |
Add this to all your code files. I placed this in a small include file that I always include as the last one in each CPP file.
Let’s assume you produce the following memory leak in main.cpp:
int main(int argc, char *argv[]) { char *foo = new char[100]; return 0; } |
Now we get the following report:
.\main.cpp(2) : {271457} normal block at 0x020D6220, 100 bytes long.
Note that we can see the source file (main.cpp) name and line number (2).
Now I replace the default reporting function with something that only reports leaks that come with source file/line number info.
This is the header file reportingHook.h:
#pragma once #if defined(WIN32) void setFilterDebugHook(void); #endif |
This is the body file reportingHook.cpp:
#if defined(WIN32) #include <string.h> #include "crtdbg.h" #define FALSE 0 #define TRUE 1 _CRT_REPORT_HOOK prevHook; int reportingHook(int reportType, char* userMessage, int* retVal) { // This function is called several times for each memory leak. // Each time a part of the error message is supplied. // This holds number of subsequent detail messages after // a leak was reported const int numFollowupDebugMsgParts = 2; static bool ignoreMessage = false; static int debugMsgPartsCount = 0; // check if the memory leak reporting starts if ((strncmp(userMessage,"Detected memory leaks!\n", 10) == 0) || ignoreMessage) { // check if the memory leak reporting ends if (strncmp(userMessage,"Object dump complete.\n", 10) == 0) { _CrtSetReportHook(prevHook); ignoreMessage = false; } else ignoreMessage = true; // something from our own code? if(strstr(userMessage, ".cpp") == NULL) { if(debugMsgPartsCount++ < numFollowupDebugMsgParts) // give it back to _CrtDbgReport() to be printed to the console return FALSE; else return TRUE; // ignore it } else { debugMsgPartsCount = 0; // give it back to _CrtDbgReport() to be printed to the console return FALSE; } } else // give it back to _CrtDbgReport() to be printed to the console return FALSE; }; void setFilterDebugHook(void) { //change the report function to only report memory leaks from program code prevHook = _CrtSetReportHook(reportingHook); } #endif |
The function setFilterDebugHook must be called at program end:
#include ... #include "reportingHook.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); int result = app.exec(); #if defined(WIN32) && defined(_DEBUG) setFilterDebugHook(); #endif return result ; } |
That’s all! Now the memory leak report will only show those occurences that originate from our own source code. But don’t forget to add the #include "reportingHook.h" to all your files or you won’t see your own memory leaks! I tested all this with Visual Studio 2008 and Qt 4.5.
I hope this helped.
