_CrtDumpMemoryLeaks

Visual Studio 6.0

Dumps all of the memory blocks in the debug heap when a memory leak has occurred (debug version only).

int _CrtDumpMemoryLeaks( void );

Routine Required Header Compatibility
_CrtDumpMemoryLeaks <crtdbg.h> Win NT, Win 95

For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBCD.LIB Single thread static library, debug version
LIBCMTD.LIB Multithread static library, debug version
MSVCRTD.LIB Import library for MSVCRTD.DLL, debug version

Return Value

_CrtDumpMemoryLeaks returns TRUE if a memory leak is found; otherwise, the function returns FALSE.

Remarks

The _CrtDumpMemoryLeaks function determines whether a memory leak has occurred since the start of program execution. When a leak is found, the debug header information for all of the objects in the heap is dumped in a user-readable form. When _DEBUG is not defined, calls to _CrtDumpMemoryLeaks are removed during preprocessing.

_CrtDumpMemoryLeaks is frequently called at the end of program execution to verify that all memory allocated by the application has been freed. The function can be called automatically at program termination by turning on the _CRTDBG_LEAK_CHECK_DF bit field of the _crtDbgFlag flag using the _CrtSetDbgFlag function.

_CrtDumpMemoryLeaks calls _CrtMemCheckpoint to obtain the current state of the heap and then scans the state for blocks that have not been freed. When an unfreed block is encountered, _CrtDumpMemoryLeaks calls _CrtMemDumpAllObjectsSince to dump information for all of the objects allocated in the heap from the start of program execution.

By default, internal C run-time blocks (_CRT_BLOCK) are not included in memory dump operations. The _CrtSetDbgFlag function can be used to turn on the _CRTDBG_CHECK_CRT_DF bit of _crtDbgFlag to include these blocks in the leak detection process.

For more information about heap state functions and the _CrtMemState structure, see the Heap State Reporting Functions. For information about how memory blocks are allocated, initialized, and managed in the debug version of the base heap, see Memory Management and the Debug Heap.

Example

/*****************************************************************
 *  EXAMPLE  1                                                   *
 *  This simple program illustrates the basic debugging features *
 *  of the C runtime libraries, and the kind of debug output     *
 *  that these features generate.                                *
 *****************************************************************/

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <crtdbg.h>

// This routine place comments at the head of a section of debug output
void OutputHeading( const char * explanation )
{
   _RPT1( _CRT_WARN, "\n\n%s:\n**************************************\
************************************\n", explanation );
}

// The following macros set and clear, respectively, given bits
// of the C runtime library debug flag, as specified by a bitmask.
#ifdef   _DEBUG
#define  SET_CRT_DEBUG_FIELD(a) \
            _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
#define  CLEAR_CRT_DEBUG_FIELD(a) \
            _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
#else
#define  SET_CRT_DEBUG_FIELD(a)   ((void) 0)
#define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0)
#endif


void main( )
{
   char *p1, *p2;
   _CrtMemState s1, s2, s3;

   // Send all reports to STDOUT
   _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 );

   // Allocate 2 memory blocks and store a string in each
   p1 = malloc( 34 );
   strcpy( p1, "This is the p1 string (34 bytes)." );

   p2 = malloc( 34 );
   strcpy( p2, "This is the p2 string (34 bytes)." );


   OutputHeading(
      "Use _ASSERTE to check that the two strings are identical" );
   _ASSERTE( strcmp( p1, p2 ) == 0 );

   OutputHeading(
      "Use a _RPT macro to report the string contents as a warning" );
   _RPT2( _CRT_WARN, "p1 points to '%s' and \np2 points to '%s'\n", p1, p2 );

   OutputHeading(
      "Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations" );
   _CrtMemDumpAllObjectsSince( NULL );

   free( p2 );

   OutputHeading(
      "Having freed p2, dump allocation information about p1 only" );
   _CrtMemDumpAllObjectsSince( NULL );

   // Store a memory checkpoint in the s1 memory-state structure
   _CrtMemCheckpoint( &s1 );

   // Allocate another block, pointed to by p2
   p2 = malloc( 38 );
   strcpy( p2, "This new p2 string occupies 38 bytes.");

   // Store a 2nd memory checkpoint in s2
   _CrtMemCheckpoint( &s2 );

   OutputHeading(
      "Dump the changes that occurred between two memory checkpoints" );
   if ( _CrtMemDifference( &s3, &s1, &s2 ) )
      _CrtMemDumpStatistics( &s3 );

   // Free p2 again and store a new memory checkpoint in s2
   free( p2 );
   _CrtMemCheckpoint( &s2 );

   OutputHeading(
      "Now the memory state at the two checkpoints is the same" );
   if ( _CrtMemDifference( &s3, &s1, &s2 ) )
      _CrtMemDumpStatistics( &s3 );

   strcpy( p1, "This new p1 string is over 34 bytes" );
   OutputHeading( "Free p1 after overwriting the end of the allocation" );
   free( p1 );

   // Set the debug-heap flag so that freed blocks are kept on the
   // linked list, to catch any inadvertent use of freed memory
   SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );

   p1 = malloc( 10 );
   free( p1 );
   strcpy( p1, "Oops" );

   OutputHeading( "Perform a memory check after corrupting freed memory" );
   _CrtCheckMemory( );

   // Use explicit calls to _malloc_dbg to save file name and line number
   // information, and also to allocate Client type blocks for tracking
   p1 = _malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ );
   p2 = _malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ );
   strcpy( p1, "p1 points to a Normal allocation block" );
   strcpy( p2, "p2 points to a Client allocation block" );

   // You must use _free_dbg to free a Client block
   OutputHeading(
      "Using free( ) to free a Client block causes an assertion failure" );
   free( p1 );
   free( p2 );

   p1 = malloc( 10 );
   OutputHeading( "Examine outstanding allocations (dump memory leaks)" );
   _CrtDumpMemoryLeaks( );

   // Set the debug-heap flag so that memory leaks are reported when
   // the process terminates. Then, exit.
   OutputHeading( "Program exits without freeing a memory block" );
   SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
}

Output

Use _ASSERTE to check that the two strings are identical:
**************************************************************************
C:\DEV\EXAMPLE1.C(56) : Assertion failed: strcmp( p1, p2 ) == 0


Use a _RPT macro to report the string contents as a warning:
**************************************************************************
p1 points to 'This is the p1 string (34 bytes).' and
p2 points to 'This is the p2 string (34 bytes).'


Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations:
**************************************************************************
Dumping objects ->
{13} normal block at 0x00660B5C, 34 bytes long
 Data: <This is the p2 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 32 20 73
{12} normal block at 0x00660B10, 34 bytes long
 Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73
Object dump complete.


Having freed p2, dump allocation information about p1 only:
**************************************************************************
Dumping objects ->
{12} normal block at 0x00660B10, 34 bytes long
 Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73
Object dump complete.


Dump the changes that occurred between two memory checkpoints:
**************************************************************************
0 bytes in 0 Free Blocks.
38 bytes in 1 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 IgnoreClient Blocks.
0 bytes in 0 (null) Blocks.
Largest number used: 4 bytes.
Total allocations: 38 bytes.


Now the memory state at the two checkpoints is the same:
**************************************************************************


Free p1 after overwriting the end of the allocation:
**************************************************************************
memory check error at 0x00660B32 = 0x73, should be 0xFD.
memory check error at 0x00660B33 = 0x00, should be 0xFD.
DAMAGE: after Normal block (#12) at 0x00660B10.


Perform a memory check after corrupting freed memory:
**************************************************************************
memory check error at 0x00660B10 = 0x4F, should be 0xDD.
memory check error at 0x00660B11 = 0x6F, should be 0xDD.
memory check error at 0x00660B12 = 0x70, should be 0xDD.
memory check error at 0x00660B13 = 0x73, should be 0xDD.
memory check error at 0x00660B14 = 0x00, should be 0xDD.
DAMAGE: on top of Free block at 0x00660B10.
DAMAGED located at 0x00660B10 is 10 bytes long.


Using free( ) to free a Client block causes an assertion failure:
**************************************************************************
dbgheap.c(1039) : Assertion failed: pHead->nBlockUse == nBlockUse


Examine outstanding allocations (dump memory leaks):
**************************************************************************
Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00660BE4, 10 bytes long
 Data: <          > CD CD CD CD CD CD CD CD CD CD
Object dump complete.


Program exits without freeing a memory block:
**************************************************************************
Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00660BE4, 10 bytes long
 Data: <          > CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Debug Functions

Show: