At my new job I found myself chasing some memory leaks in our rather large C/C++ codebase. Going into the task I was optimistic and just a bit overconfident, knowing as I did that the C Runtime (CRT) has built-in leak-finding goodness.
After the honeymoon, it became clear I was mistaken. Sure, you can set the _CRTDBG_LEAK_CHECK_DF flag with _CrtSetDbgFlag. You can even enable source information with _CRTDBG_MAP_ALLOC. Go ahead. Try it. Use this code:
#include "stdafx.h"
extern "C" int main(INT argc, TCHAR *argv[])
{
char* c = new char[2048];
::strcpy(c, "You're screwed, pal!");
return 0;
}
What? The line number reported for the leak is some bullshit location deep within the CRT? How can this be? The CRT is better than that!
Not. The CRT provides debug versions of those canonical C-isms malloc and free, but not the more enlightened C++ staples new and delete. For that, you have to roll your own. Here’s how I roll:
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
‘Ah’, you’re thinking, ‘that wasn’t so bad’. It’s not over yet. Now add a #include <set> after your DEBUG_NEW cruft; from the uncontrollable sobbing I take it you’ve seen the torrent of inscrutable compile errors you got. That’s because the debug new breaks STL which does its own slightly-off-reservation heap stuff.
The solution? Don’t do that. Include STL headers before your DEBUG_NEW stuff. Can’t do that cleanly? Tough shit. You must not want source information that badly.