Detecting Memory Leaks

This article describes how to get the callstack for memory leaks in a certain component (EXE or DLL) of your Visual C++ program. The code provided with this article works on WindowsNT. It should work on Windows9x systems as well, although it has not been tested on such systems. There is another restriction, that it only works on Intel x86 machines. It has been written with MS Visual C/C++ 5.0, but it should work fine with Version 6 of the Developer Studio as well. The example program is written with the Active Template Library (ATL), but it does not contain any COM stuff.

Usage

To detect memory leaks in the components of your application, you just have to add the following lines anywhere to the code of your component:


	#include "c:\temp\HookAlloc\MemoryTracking.h"
	USE_MEMORYTRACKING("c:\\temp\\allocations.log",true)
	#pragma warning(disable:4073)							
	#pragma init_seg(lib)
  • the path in the #include-statement has to be adapted to your needs
  • The Macro USE_MEMORYTRACKING("c:\\temp\\allocations.log", bLogAtStartup) defines the name of the Logfile (if NULL, all output is written to the debug output window) and specifies, whether logging is on or off at program startup
  • To control the parts of your program where logging is on / off use the macros LOGGING_ON / LOGGING_OFF or BEGIN_NO_LOG_BLOCK / END_NO_LOG_BLOCK to switch off logging for a special part of code within a single function/method.
  • The pragma you see above switches off the stupid compiler warning that an 'initializer has been put in "lib" initialisation area'. This warning is not needed at all, since we know what we are doing with the next line: MemoryTracking is set up before any of the "users objects" (like MFC's CWinApp derived object) are initialized.

Then:
  • recompile your component (rebuild is NOT neccessary)
  • start your program, and invoke those parts of it, where the leaks occur
  • terminate the program and you'll get a list of memory leaks in your debug window of VC++
  • open the log file, that has been defined with the macro USE_MEMORYTRACKING (see above) or take a look into the VC++ debug output window, depending if you have defined a log filename or not
  • compare the numbers enclosed in curly braces (i.e. {1234} with the 'request'-numbers in the log file (or in the debug output window)

By looking at the call stack in the logfile, you may figure out which function or method has allocated the leak.

Tip:

If MFC is used, you may add the line '#define new DEBUG_NEW' to the cpp files of the project. Thus you provide information about where allocations occur to the new operator. For allocations (leaks) that have been made with DEBUG_NEW defined you can simply double-click the line preceeding the call stack of a leak description (in the debug output window) to jump to the appropriate position in the source code.

  • Please note that this mechanism only works in Debug mode and that it severly affects the execution speed of your program. This code has not been developed to be included permanently in your code, it should only be used to detect memory leaks.
  • Please not that the code can detect only those leaks that are caused in the component (DLL, OCX, EXE, ...) where tracking is enabled. Tracking can only be enabled for one single component.

    Downloads

    Download demo project - 11 Kb



  • Comments

    • Doesn't work

      Posted by Legacy on 12/18/2002 12:00am

      Originally posted by: Maciej Misiak

      I think this should be little quicker... I started my server application and waited 20 minutes. Memory use has grown from 5MB to 125MB (ca. 100kB/sec.) and didn't want to stop grow. I killed this process. Without this MemoryLeakFinder it starts in 10 secs.

      Reply
    • some help...

      Posted by Legacy on 11/13/2002 12:00am

      Originally posted by: David Huelves Ramos

      I you have memory leaks:
      
      

      1) first take note of the address of the memory that is not free when program finish
      2)then open the memory spy (from debug toolbar inside VC++ environment) stop the program in debug mode at the beginning.
      3)set the memory spy to the address location u got on step "1)".
      4) go step by step until this memory possition is filled.

      5)then you know which part of your program is filling it, so you have to look why it doesn't free it when the program finish.

      hope this helps.

      remember to free all allocated memory using destructors...

      Reply
    • Doesn't catch 'COM-type" leaks

      Posted by Legacy on 04/30/2002 12:00am

      Originally posted by: Robin

      Hi,
      
      

      I just gave this a try and it works, but only to an extent. It doesn't catch the types of leaks you're most likely to see in a COM/ATL component. For example, I added the following pieces of code to test MemoryTracker:

      int* pNum = new int(3);
      BSTR dbgStr = SysAllocString(L"Pokey & Gumby");
      int* pNum2 = (int*)CoTaskMemAlloc(7);

      It caught the 1st one but did not catch the other two. This is the same problem as when attempting to use the _CrtMem functions (e.g. _CrtMemCheckpoint, etc) :-(

      Regards,
      Robin

      Reply
    • A simpler way...

      Posted by Legacy on 04/16/2002 12:00am

      Originally posted by: rui costa

      I think I've got a better way to detect memory leaks: the _CrtSetDbgFlag function.
      
      It's provided by the windows API, it's easy to use and very safe.

      You just need to call CrtSetDbgFlag anywhere in your code !
      Here is a simple:


      #include <crtdbg.h>

      #ifdef _DEBUG
      #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
      #undef THIS_FILE
      static char THIS_FILE[] = __FILE__;
      #endif

      void main()
      {
      _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

      char* memory_leak = new char[256];
      }

      And that's all !

      If your program has memory leaks, you'll be informed at the end of the program execution.
      Check in the debug window for errors.
      If you have errors, double click over the error message and you'll know the line where your program has allocated the memory.

      If you need more specific information, you can use this class:

      class FindMemoryLeaks
      {
      _CrtMemState m_checkpoint;

      public:

      FindMemoryLeaks()
      {
      _CrtMemCheckpoint(&m_checkpoint);
      };

      ~FindMemoryLeaks()
      {
      _CrtMemState checkpoint;
      _CrtMemCheckpoint(&checkpoint);

      _CrtMemState diff;
      _CrtMemDifference(&diff, &m_checkpoint, &checkpoint);

      _CrtMemDumpStatistics(&diff);
      _CrtMemDumpAllObjectsSince(&diff);
      };
      };

      Put it in the beginning of your program.
      Good look !

      Reply
    • memory leaks

      Posted by Legacy on 03/21/2002 12:00am

      Originally posted by: S.Senthil Kumar

      i was looking for this code Thanks i will use it hereafter

      Reply
    • Memory Leak Problem

      Posted by Legacy on 02/08/2002 12:00am

      Originally posted by: Kalpesh

      Hi,
      Thanks a lot for valuable information on this site.
      However, I haven't got exact solution to my problem.
      My server application keeps on consuming memory, and when i gracefully shutdown the server, i dont see any memory leaks in debug window. But looking at the process table, i'm sure that my server is idling, but still keeps on increasing 4K every minute or so.
      Can you guide me to find such problem?
      Thanks,
      Kalpesh

      Reply
    • error C2664

      Posted by Legacy on 01/21/2002 12:00am

      Originally posted by: Anonymous

      I added your code at the top of my code:
      -------------//-----------
      #include "c:\\foo\\MemoryTracking.h"
      USE_MEMORYTRACKING(MT,"c:\\foo\\allocs.log")
      #pragma warning(disable:4073)
      #pragma warning(disable:4786)
      #pragma init_seg(lib)
      --------------//-------------

      But I get this error message:
      ********************************************************
      c:\\foo\\memorytracking.h(279) : error C2664: '_CrtSetAllocHook' : cannot convert parameter 1 from 'int (__cdecl *)(int,void *,unsigned int,int,long,const char *,int)' to 'int (__cdecl *)(int,void *,unsigned int,int,long,const unsigned char *,int)'
      This conversion requires a reinterpret_cast, a C-style cast or function-style cast
      *******************************************************

      What am I doing wrong???

      Reply
    • This is a very neat tool.

      Posted by Legacy on 09/19/2001 12:00am

      Originally posted by: Vicky Wallace

      Thanks

      Reply
    • [Question] file name and line number were not dsiplayed.

      Posted by Legacy on 04/03/2001 12:00am

      Originally posted by: Seung-Hoon Lee

      Hi, users.

      I am Seung-Hoon Lee. When I read this article, I was excite.
      So, I ran this sample and got a below log file.

      As seen as you read the below log, I didn't get the detail file name and line number that the memory leak happened.

      Could you help me make the file name and line number display ?

      .....

      [allocs.txt]

      Alloc: request=49, size=100, blocktype=_NORMAL_BLOCK, file=(null), line=0
      C:\WINNT\System32\ntdll.dll section: 1 offset: 181
      operator new +14 bytes sig: ??2@YAPAXI@Z decl: void * __cdecl operator new(unsigned int)
      _Function +16 bytes sig: _Function decl: _Function
      _WinMain@16 +85 bytes sig: _WinMain@16 decl: _WinMain@16
      _WinMainCRTStartup +275 bytes sig: _WinMainCRTStartup decl: _WinMainCRTStartup
      SetStdHandle +22 bytes sig: SetStdHandle decl: SetStdHandle
      Alloc: request=50, size=50, blocktype=_NORMAL_BLOCK, file=(null), line=0
      C:\WINNT\System32\ntdll.dll section: 1 offset: 181
      operator new +14 bytes sig: ??2@YAPAXI@Z decl: void * __cdecl operator new(unsigned int)
      ThreadProc +16 bytes sig: ?ThreadProc@@YGKPAX@Z decl: unsigned long __stdcall ThreadProc(void *)
      RegisterConsoleVDM +519 bytes sig: RegisterConsoleVDM decl: RegisterConsoleVDM
      Number of Memory Leaks in Module: 2

      Reply
    • Detecting memory leaks.

      Posted by Legacy on 01/24/2001 12:00am

      Originally posted by: Howard Harvey

      While Stefan does do an admirable job of showing
      how to catch memory leaks, my personal favorite
      tool for the job is still BoundsChecker by
      NuMega/Compuware. Just personal preference.

      Reply
    • Loading, Please Wait ...

    Leave a Comment
    • Your email address will not be published. All fields are required.

    Top White Papers and Webcasts

    • On-demand Event Event Date: March 27, 2014 Teams need to deliver quality software faster and need integrated agile planning, task tracking, source control, auto deploy with continuous builds and a configurable process to adapt to the way you work. Rational Team Concert and DevOps Services (JazzHub) have everything you need to build great software, integrated seamlessly together right out of the box or available immediately in the cloud. And with the Rational Team Concert Client, you can connect your …

    • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

    Most Popular Programming Stories

    More for Developers

    Latest Developer Headlines

    RSS Feeds