How to detect memory leaks and other memory errors in Visual C++:

First, make the following changes to your Project Settings (select Project -> Settings... from the menu):

  1. Select the C/C++ tab.
  2. Make sure Category combo box is set to General.
  3. In the Preprocessor definitions field, make sure you have the following entries:
    WIN32,_DEBUG,_CONSOLE,_MBCS,_AFXDLL

    (You will most likely need to add _AFXDLL to the end).

  4. Make sure Category is set to Code Generation.
  5. In the Use run-time library combo box, select Debug Multithreaded DLL.
  6. Click the OK button.
  7. At the top of your source file, add the following lines:
    #include <afx.h>
    #include <crtdbg.h>
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
  8. Now try to compile your program.  If this works, then go on to the next step.  If it doesn't,
    then double-check your project settings and try adding the following before the lines you added
    in step 7:
    #include <string>
    #include <iostream>
  9. Try to dynamically allocate an array by using the new operator, but
    don't call delete[] on the array.
  10. When you compile and run your program now, you will see a new listing
    called Dumping objects in your Output window (the one that always appears
    when you compile something). Double-clicking on the entries under Dumping
    objects will take you to the lines in your source file where you allocated
    memory but failed to deallocate the memory before the exit of the program.
    If you now modify your program to delete the dynamically-allocated array
    before program's end, you will not see the listing under Dumping objects
    after you run your program.

Notes:

Feihong Hsu
fhsu@cs.uic.edu
April 21, 2003

-----------------------------------------------------------------------------------------------

#include <iostream>
#include <string>
#include <cassert>
using namespace std;

#include <afx.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Some helpful but not entirely necessary macros:

// Tweak the behavior of the debug heap:
#define SetDebugFlags                                    \
    int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );  \
    tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;                  \
    tmpFlag |= _CRTDBG_LEAK_CHECK_DF;                    \
    _CrtSetDbgFlag( tmpFlag );  

// Send all memory error reports to stdout instead of the Output window:
#define SendReportsToStdout     \
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );     \
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );   \
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );    \
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );  \
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );   \
    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );

int main()
{
    int* intArray = new int[45];
   
    intArray[4] = 56;
    intArray[44] = 322;
    intArray[45] = 4342;   // oops, corrupted the memory!
    intArray[-1] = 31;     // oops, did it again!
    // _CrtCheckMemory();     //  set a breakpoint, or else just wrap an assert around it
   
    delete[] intArray;
   
    return 0;
}