Share via


Diagnostic Services

 

The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.

The latest version of this topic can be found at Diagnostic Services.

The Microsoft Foundation Class Library supplies many diagnostic services that make debugging your programs easier. These diagnostic services include macros and global functions that allow you to track your program's memory allocations, dump the contents of objects during run time, and print debugging messages during run time. The macros and global functions for diagnostic services are grouped into the following categories:

  • General diagnostic macros

  • General diagnostic functions and variables

  • Object diagnostic functions

These macros and functions are available for all classes derived from CObject in the Debug and Release versions of MFC. However, all except DEBUG_NEW and VERIFY do nothing in the Release version.

In the Debug library, all allocated memory blocks are bracketed with a series of "guard bytes." If these bytes are disturbed by an errant memory write, then the diagnostic routines can report a problem. If you include the line:

#define new DEBUG_NEW

in your implementation file, all calls to new will store the filename and line number where the memory allocation took place. The function [CMemoryState::DumpAllObjectsSince]--brokenlink--(../Topic/CMemoryState%20Class.md#cmemorystate__dumpallobjectssince) will display this extra information, allowing you to identify memory leaks. Refer also to the class CDumpContext for additional information on diagnostic output.

In addition, the C run-time library also supports a set of diagnostic functions you can use to debug your applications. For more information, see Debug Routines in the Run-Time Library Reference.

MFC General Diagnostic Macros

ASSERT) Prints a message and then aborts the program if the specified expression evaluates to FALSE in the Debug version of the library.
ASSERT_KINDOF Tests that an object is an object of the specified class or of a class derived from the specified class.
ASSERT_VALID Tests the internal validity of an object by calling its AssertValid member function; typically overridden from CObject.
DEBUG_NEW Supplies a filename and line number for all object allocations in Debug mode to help find memory leaks.
DEBUG_ONLY Similar to ASSERT but does not test the value of the expression; useful for code that should execute only in Debug mode.
TRACE Provides printf-like capability in the Debug version of the library.
VERIFY Similar to ASSERT but evaluates the expression in the Release version of the library as well as in the Debug version.

MFC General Diagnostic Variables and Functions

afxDump Global variable that sends CDumpContext information to the debugger output window or to the debug terminal.
afxMemDF Global variable that controls the behavior of the debugging memory allocator.
AfxCheckError Global variable used to test the passed SCODE to see if it is an error and, if so, throws the appropriate error.
AfxCheckMemory Checks the integrity of all currently allocated memory.
AfxDump If called while in the debugger, dumps the state of an object while debugging.
AfxDumpStack Generate an image of the current stack. This function is always linked statically.
AfxEnableMemoryLeakDump Enables the memory leak dump.
AfxEnableMemoryTracking Turns memory tracking on and off.
AfxIsMemoryBlock Verifies that a memory block has been properly allocated.
AfxIsValidAddress Verifies that a memory address range is within the program's bounds.
AfxIsValidString Determines whether a pointer to a string is valid.
AfxSetAllocHook Enables the calling of a function on each memory allocation.

MFC Object Diagnostic Functions

AfxDoForAllClasses Performs a specified function on all CObject-derived classes that support run-time type checking.
AfxDoForAllObjects Performs a specified function on all CObject-derived objects that were allocated with new.

ASSERT (MFC)

Evaluates its argument.

ASSERT
(booleanExpression)   

Parameters

booleanExpression
Specifies an expression (including pointer values) that evaluates to nonzero or 0.

Remarks

If the result is 0, the macro prints a diagnostic message and aborts the program. If the condition is nonzero, it does nothing.

The diagnostic message has the form

assertion failed in file <name> in line <num>

where name is the name of the source file, and num is the line number of the assertion that failed in the source file.

In the Release version of MFC, ASSERT does not evaluate the expression and thus will not interrupt the program. If the expression must be evaluated regardless of environment, use the VERIFY macro in place of ASSERT.

Note

This function is available only in the Debug version of MFC.

Example

      CAge* pcage = new CAge(21); // CAge is derived from CObject.
      ASSERT(pcage != NULL);
      ASSERT(pcage->IsKindOf(RUNTIME_CLASS(CAge)));
      // Terminates program only if pcage is NOT a CAge*.   

ASSERT_KINDOF

This macro asserts that the object pointed to is an object of the specified class, or is an object of a class derived from the specified class.

ASSERT_KINDOF
(classname, pobject)  

Parameters

classname
The name of a CObject-derived class.

pobject
A pointer to a class object.

Remarks

The pobject parameter should be a pointer to an object and can be const. The object pointed to and the class must support CObject run-time class information. As an example, to ensure that pDocument is a pointer to an object of the CMyDoc class, or any of its derivatives, you could code:

   ASSERT_KINDOF(CMyDoc, pDocument);

Using the ASSERT_KINDOF macro is exactly the same as coding:

   ASSERT(pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));

This function works only for classes declared with the [DECLARE_DYNAMIC]--brokenlink--(../Topic/not%20found.md#declare_dynamic or [DECLARE_SERIAL]--brokenlink--(../Topic/not%20found.md#declare_serial) macro.

Note

This function is available only in the Debug version of MFC.

ASSERT_VALID

Use to test your assumptions about the validity of an object's internal state.

ASSERT_VALID
(pObject)   

Parameters

pObject
Specifies an object of a class derived from CObject that has an overriding version of the AssertValid member function.

Remarks

ASSERT_VALID calls the AssertValid member function of the object passed as its argument.

In the Release version of MFC, ASSERT_VALID does nothing. In the Debug version, it validates the pointer, checks against NULL, and calls the object's own AssertValid member functions. If any of these tests fails, an alert message is displayed in the same manner as ASSERT.

Note

This function is available only in the Debug version of MFC.

For more information and examples, see Debugging MFC Applications.

Example

      // Assure that pMyObject is a valid pointer to an
      // object derived from CObject.
      ASSERT_VALID(pMyObject);

DEBUG_NEW

Assists in finding memory leaks.

#define  new DEBUG_NEW   

Remarks

You can use DEBUG_NEW everywhere in your program that you would ordinarily use the new operator to allocate heap storage.

In debug mode (when the _DEBUG symbol is defined), DEBUG_NEW keeps track of the filename and line number for each object that it allocates. Then, when you use the [CMemoryState::DumpAllObjectsSince]--brokenlink--(../Topic/CMemoryState%20Class.md#cmemorystate__dumpallobjectssince) member function, each object allocated with DEBUG_NEW is shown with the filename and line number where it was allocated.

To use DEBUG_NEW, insert the following directive into your source files:

#define new DEBUG_NEW

Once you insert this directive, the preprocessor will insert DEBUG_NEW wherever you use new, and MFC does the rest. When you compile a release version of your program, DEBUG_NEW resolves to a simple new operation, and the filename and line number information are not generated.

Note

In previous versions of MFC (4.1 and earlier) you needed to put the #define statement after all statements that called the IMPLEMENT_DYNCREATE or IMPLEMENT_SERIAL macros. This is no longer necessary.

DEBUG_ONLY

In debug mode (when the _DEBUG symbol is defined), DEBUG_ONLY evaluates its argument.

DEBUG_ONLY
(expression)   

Remarks

In a release build, DEBUG_ONLY does not evaluate its argument. This is useful when you have code that should be executed only in debug builds.

The DEBUG_ONLY macro is equivalent to surrounding expression with #ifdef _DEBUG and #endif.

Example

void ExampleFunc(char* p, int size, char fill)
{
   char* q;               // working copy of pointer 
   VERIFY(q = p);         // copy buffer pointer and validate
   ASSERT(size >= 100);   // make sure buffer is at least 100 bytes
   ASSERT(isalpha(fill)); // make sure fill character is alphabetic
   // if fill character is invalid, substitute 'X' so we can continue
   // debugging after the preceding ASSERT fails.
   DEBUG_ONLY(fill = (isalpha(fill)) ? fill : 'X');
}

TRACE

Sends the specified string to the debugger of the current application.

TRACE
(exp)  
TRACE
(DWORD  category,  UINT  level, LPCSTR lpszFormat, ...)   

Remarks

See ATLTRACE2 for a description of TRACE. TRACE and ATLTRACE2 have the same behavior.

In the debug version of MFC, this macro sends the specified string to the debugger of the current application. In a release build, this macro compiles to nothing (no code is generated at all).

For more information, see Debugging MFC Applications.

VERIFY

In the Debug version of MFC, evaluates its argument.

VERIFY
(booleanExpression)   

Parameters

booleanExpression
Specifies an expression (including pointer values) that evaluates to nonzero or 0.

Remarks

If the result is 0, the macro prints a diagnostic message and halts the program. If the condition is nonzero, it does nothing.

The diagnostic message has the form

assertion failed in file <name> in line <num>

where name is the name of the source file and num is the line number of the assertion that failed in the source file.

In the Release version of MFC, VERIFY evaluates the expression but does not print or interrupt the program. For example, if the expression is a function call, the call will be made.

Example

   // VERIFY can be used for things that should never fail, though
   // you may want to make sure you can provide better error recovery
   // if the error can actually cause a crash in a production system.

   // It _is_ possible that GetDC() may fail, but the out-of-memory
   // condition that causes it isn't likely. For a test application,
   // this use of VERIFY() is fine. For any production code, this
   // usage is dubious.

   // get the display device context
   HDC hdc;
   VERIFY((hdc = ::GetDC(hwnd)) != NULL);

   // give the display context back
   ::ReleaseDC(hwnd, hdc);

afxDump (CDumpContext in MFC)

Provides basic object-dumping capability in your application.

CDumpContext  afxDump;   

Remarks

afxDump is a predefined CDumpContext object that allows you to send CDumpContext information to the debugger output window or to a debug terminal. Typically, you supply afxDump as a parameter to CObject::Dump.

Under Windows NT and all versions of Windows, afxDump output is sent to the Output-Debug window of Visual C++ when you debug your application.

This variable is defined only in the Debug version of MFC. For more information on afxDump, see Debugging MFC Applications.

Example

      // example for afxDump
      CPerson* pMyPerson = new CPerson;
      // set some fields of the CPerson object...
      //..
      // now dump the contents
      #ifdef _DEBUG
      afxDump << _T("Dumping myPerson:\n");
      pMyPerson->Dump(afxDump);
      afxDump << _T("\n");
      #endif

afxMemDF

This variable is accessible from a debugger or your program and allows you to tune allocation diagnostics.

int  afxMemDF;  

Remarks

afxMemDF can have the following values as specified by the enumeration afxMemDF:

  • allocMemDF Turns on debugging allocator (default setting in Debug library).

  • delayFreeMemDF Delays freeing memory. While your program frees a memory block, the allocator does not return that memory to the underlying operating system. This will place maximum memory stress on your program.

  • checkAlwaysMemDF Calls AfxCheckMemory every time memory is allocated or freed. This will significantly slow memory allocations and deallocations.

Example

      afxMemDF = allocMemDF | checkAlwaysMemDF;   

AfxCheckError

This function tests the passed SCODE to see if it is an error.

void AFXAPI AfxCheckError(SCODE sc);
throw CMemoryException* 
throw COleException*  

Remarks

If it is an error, the function throws an exception. If the passed SCODE is E_OUTOFMEMORY, the function throws a CMemoryException by calling [AfxThrowMemoryException]--brokenlink--(../Topic/not%20found.md#afxthrowmemoryexception). Otherwise, the function throws a COleException by calling [AfxThrowOleException]--brokenlink--(../Topic/not%20found.md#afxthrowoleexception).

This function can be used to check the return values of calls to OLE functions in your application. By testing the return value with this function in your application, you can properly react to error conditions with a minimal amount of code.

Note

This function has the same effect in debug and non-debug builds.

Example

      AfxCheckError(::CoCreateInstance(clsidWMP, NULL, CLSCTX_INPROC_SERVER, 
         IID_IDispatch, (LPVOID*)&pWMPDispatch));

      oddWMP.AttachDispatch(pWMPDispatch, TRUE);

AfxCheckMemory

This function validates the free memory pool and prints error messages as required.

BOOL  AfxCheckMemory(); 

Return Value

Nonzero if no memory errors; otherwise 0.

Remarks

If the function detects no memory corruption, it prints nothing.

All memory blocks currently allocated on the heap are checked, including those allocated by new but not those allocated by direct calls to underlying memory allocators, such as the malloc function or the GlobalAlloc Windows function. If any block is found to be corrupted, a message is printed to the debugger output.

If you include the line

#define new DEBUG_NEW

in a program module, then subsequent calls to AfxCheckMemory show the filename and line number where the memory was allocated.

Note

If your module contains one or more implementations of serializable classes, then you must put the #define line after the last IMPLEMENT_SERIAL macro call.

This function works only in the Debug version of MFC.

Example

      CAge* pcage = new CAge(21);  // CAge is derived from CObject.
      Age* page = new Age(22);     // Age is NOT derived from CObject.
      *(((char*)pcage) - 1) = 99;   // Corrupt preceding guard byte
      *(((char*)page) - 1) = 99;    // Corrupt preceding guard byte
      AfxCheckMemory();

AfxDump (MFC)

Call this function while in the debugger to dump the state of an object while debugging.

void AfxDump(const CObject* pOb); 

Parameters

pOb
A pointer to an object of a class derived from CObject.

Remarks

AfxDump calls an object's Dump member function and sends the information to the location specified by the afxDump variable. AfxDump is available only in the Debug version of MFC.

Your program code should not call AfxDump, but should instead call the Dump member function of the appropriate object.

AfxDumpStack

This global function can be used to generate an image of the current stack.

void AFXAPI AfxDumpStack(DWORD dwTarget = AFX_STACK_DUMP_TARGET_DEFAULT); 

Parameters

dwTarget
Indicates the target of the dump output. Possible values, which can be combined using the bitwise-OR ( |) operator, are as follows:

  • AFX_STACK_DUMP_TARGET_TRACE Sends output by means of the TRACE macro. The TRACE macro generates output in debug builds only; it generates no output in release builds. Also, TRACE can be redirected to other targets besides the debugger.

  • AFX_STACK_DUMP_TARGET_DEFAULT Sends dump output to the default target. For a debug build, output goes to the TRACE macro. In a release build, output goes to the Clipboard.

  • AFX_STACK_DUMP_TARGET_CLIPBOARD Sends output to the Clipboard only. The data is placed on the Clipboard as plain text using the CF_TEXT Clipboard format.

  • AFX_STACK_DUMP_TARGET_BOTH Sends output to the Clipboard and to the TRACE macro, simultaneously.

  • AFX_STACK_DUMP_TARGET_ODS Sends output directly to the debugger by means of the Win32 function OutputDebugString(). This option will generate debugger output in both debug and release builds when a debugger is attached to the process. AFX_STACK_DUMP_TARGET_ODS always reaches the debugger (if it is attached) and cannot be redirected.

Remarks

The example below reflects a single line of the output generated from calling AfxDumpStack from a button handler in an MFC dialog application:

=== begin AfxDumpStack output ===

00427D55: DUMP2\DEBUG\DUMP2.EXE! void AfxDumpStack(unsigned long) + 181 bytes

0040160B: DUMP2\DEBUG\DUMP2.EXE! void CDump2Dlg::OnClipboard(void) + 14 bytes

0044F884: DUMP2\DEBUG\DUMP2.EXE! int _AfxDispatchCmdMsg(class CCmdTarget *,

unsigned int,int,void ( CCmdTarget::*)(void),void *,unsigned int,struct AFX_CMDHANDLE

0044FF7B: DUMP2\DEBUG\DUMP2.EXE! virtual int CCmdTarget::OnCmdMsg(unsigned

int,int,void *,struct AFX_CMDHANDLERINFO *) + 626 bytes

00450C71: DUMP2\DEBUG\DUMP2.EXE! virtual int CDialog::OnCmdMsg(unsigned

int,int,void *,struct AFX_CMDHANDLERINFO *) + 36 bytes

00455B27: DUMP2\DEBUG\DUMP2.EXE! virtual int CWnd::OnCommand(unsigned

int,long) + 312 bytes

00454D3D: DUMP2\DEBUG\DUMP2.EXE! virtual int CWnd::OnWndMsg(unsigned

int,unsigned int,long,long *) + 83 bytes

00454CC0: DUMP2\DEBUG\DUMP2.EXE! virtual long CWnd::WindowProc(unsigned

int,unsigned int,long) + 46 bytes

004528D9: DUMP2\DEBUG\DUMP2.EXE! long AfxCallWndProc(class CWnd *,struct

HWND__ *,unsigned int,unsigned int,long) + 237 bytes

00452D34: DUMP2\DEBUG\DUMP2.EXE! long AfxWndProc(struct HWND__ *,unsigned

int,unsigned int,long) + 129 bytes

BFF73663: WINDOWS\SYSTEM\KERNEL32.DLL! ThunkConnect32 + 2148 bytes

BFF928E0: WINDOWS\SYSTEM\KERNEL32.DLL! UTUnRegister + 2492 bytes

=== end AfxDumpStack() output ===

Each line in the output above indicates the address of the last function call, the full path name of the module that contains the function call, and the function prototype called. If the function call on the stack does not happen at the exact address of the function, an offset of bytes is shown.

For example, the following table describes the first line of the above output:

Output Description
00427D55: The return address of the last function call.
DUMP2\DEBUG\DUMP2.EXE! The full path name of the module that contains the function call.
void AfxDumpStack(unsigned long) The function prototype called.
+ 181 bytes The offset in bytes from the address of the function prototype (in this case, void AfxDumpStack(unsigned long)) to the return address (in this case, 00427D55).

AfxDumpStack is available in debug and nondebug versions of the MFC libraries; however, the function is always linked statically, even when your executable file uses MFC in a shared DLL. In shared-library implementations, the function is found in the MFCS42.LIB library (and its variants).

To use this function successfully:

  • The file IMAGEHLP.DLL must be on your path. If you do not have this DLL, the function will display an error message. See Image Help Library for information on the function set provided by IMAGEHLP.

  • The modules that have frames on the stack must include debugging information. If they do not contain debugging information, the function will still generate a stack trace, but the trace will be less detailed.

AfxEnableMemoryLeakDump

Enables and disables the memory leak dump in the AFX_DEBUG_STATE destructor.

BOOL AFXAPI AfxEnableMemoryLeakDump(BOOL bDump);

Parameters

[in] bDump
TRUE indicates the memory leak dump is enabled; FALSE indicates the memory leak dump is disabled.

Return Value

The previous value for this flag.

Remarks

When an application unloads the MFC library, the MFC library checks for memory leaks. At this point, any memory leaks are reported to the user through the Debug window of Visual Studio.

If your application loads another library before the MFC library, some memory allocations in that library will be incorrectly reported as memory leaks. False memory leaks can cause your application to close slowly as the MFC library reports them. In this case, use AfxEnableMemoryLeakDump to disable the memory leak dump.

Note

If you use this method to turn off the memory leak dump, you will not receive reports of valid memory leaks in your application. You should only use this method if you are confident that the memory leak report contains false memory leaks.

AfxEnableMemoryTracking

Diagnostic memory tracking is normally enabled in the Debug version of MFC.

BOOL AfxEnableMemoryTracking(BOOL bTrack); 

Parameters

bTrack
Setting this value to TRUE turns on memory tracking; FALSE turns it off.

Return Value

The previous setting of the tracking-enable flag.

Remarks

Use this function to disable tracking on sections of your code that you know are allocating blocks correctly.

For more information on AfxEnableMemoryTracking, see Debugging MFC Applications.

Note

This function works only in the Debug version of MFC.

Example

BOOL CMyWinApp::InitInstance()
{
#ifdef _DEBUG
   // Disable tracking of memory for the scope of the InitInstance()
   AfxEnableMemoryTracking(FALSE);
#endif  // _DEBUG

   // ...

#ifdef _DEBUG
   // Re-enable tracking of memory
   AfxEnableMemoryTracking(TRUE);
#endif  // _DEBUG

   return TRUE;
}

AfxIsMemoryBlock

Tests a memory address to make sure it represents a currently active memory block that was allocated by the diagnostic version of new.

BOOL AfxIsMemoryBlock(
    const void* p,  
    UINT nBytes,  
    LONG* plRequestNumber = NULL); 

Parameters

p
Points to the block of memory to be tested.

nBytes
Contains the length of the memory block in bytes.

plRequestNumber
Points to a long integer that will be filled in with the memory block's allocation sequence number, or zero if it does not represent a currently active memory block.

Return Value

Nonzero if the memory block is currently allocated and the length is correct; otherwise 0.

Remarks

It also checks the specified size against the original allocated size. If the function returns nonzero, the allocation sequence number is returned in plRequestNumber. This number represents the order in which the block was allocated relative to all other new allocations.

Example

      CAge* pcage = new CAge(21); // CAge is derived from CObject.
      ASSERT(AfxIsMemoryBlock(pcage, sizeof(CAge)));

AfxIsValidAddress

Tests any memory address to ensure that it is contained entirely within the program's memory space.

BOOL AfxIsValidAddress(
    const void* lp,  
    UINT nBytes,  
    BOOL bReadWrite = TRUE); 

Parameters

lp
Points to the memory address to be tested.

nBytes
Contains the number of bytes of memory to be tested.

bReadWrite
Specifies whether the memory is both for reading and writing ( TRUE) or just reading ( FALSE).

Return Value

In debug builds, nonzero if the specified memory block is contained entirely within the program's memory space; otherwise 0.

In non-debug builds, nonzero if lp is not NULL; otherwise 0.

Remarks

The address is not restricted to blocks allocated by new.

Example

      // Allocate a 5 character array, which should have a valid memory address.
      char* arr = new char[5];

      // Create a null pointer, which should be an invalid memory address.
      char* null = (char*)0x0;

      ASSERT(AfxIsValidAddress(arr, 5));
      ASSERT(!AfxIsValidAddress(null, 5));

AfxIsValidString

Use this function to determine whether a pointer to a string is valid.

BOOL  AfxIsValidString(
    LPCSTR lpsz,  
    int nLength = -1); 

Parameters

lpsz
The pointer to test.

nLength
Specifies the length of the string to be tested, in bytes. A value of –1 indicates that the string will be null-terminated.

Return Value

In debug builds, nonzero if the specified pointer points to a string of the specified size; otherwise 0.

In non-debug builds, nonzero if lpsz is not NULL; otherwise 0.

Example

      // Create a character string which should be valid.
      char str[12] = "hello world";

      // Create a null pointer, which should be an invalid string.
      char* null = (char*)0x0;

      ASSERT(AfxIsValidString(str, 12));
      ASSERT(!AfxIsValidString(null, 5));   

AfxSetAllocHook

Sets a hook that enables calling of the specified function before each memory block is allocated.

AFX_ALLOC_HOOK AfxSetAllocHook(AFX_ALLOC_HOOK pfnAllocHook); 

Parameters

pfnAllocHook
Specifies the name of the function to call. See the Remarks for the prototype of an allocation function.

Return Value

Nonzero if you want to permit the allocation; otherwise 0.

Remarks

The Microsoft Foundation Class Library debug-memory allocator can call a user-defined hook function to allow the user to monitor a memory allocation and to control whether the allocation is permitted. Allocation hook functions are prototyped as follows:

BOOL AFXAPI AllocHook( size_t nSize, BOOL bObject, LONG lRequestNumber );

nSize
The size of the proposed memory allocation.

bObject
TRUE if the allocation is for a CObject-derived object; otherwise FALSE.

lRequestNumber
The memory allocation's sequence number.

Note that the AFXAPI calling convention implies that the callee must remove the parameters from the stack.

AfxDoForAllClasses

Calls the specified iteration function for all serializable CObject-derived classes in the application's memory space.

void AFXAPI AfxDoForAllClasses(
    void (* pfn)(const CRuntimeClass* pClass, void* pContext),  
    void* pContext); 

Parameters

pfn
Points to an iteration function to be called for each class. The function arguments are a pointer to a CRuntimeClass object and a void pointer to extra data that the caller supplies to the function.

pContext
Points to optional data that the caller can supply to the iteration function. This pointer can be NULL.

Remarks

Serializable CObject-derived classes are classes derived using the DECLARE_SERIAL macro. The pointer that is passed to AfxDoForAllClasses in pContext is passed to the specified iteration function each time it is called.

Note

This function works only in the Debug version of MFC.

Example

#ifdef _DEBUG
void DoForAllClasses(const CRuntimeClass* pClass, void* pContext)
{
   ASSERT(pContext != NULL);
   CString *pStr = (CString *)pContext;

   *pStr += pClass->m_lpszClassName;
   *pStr += _T("\n");
}
#endif
#ifdef _DEBUG
   CString cStr;
   AfxDoForAllClasses(DoForAllClasses, &cStr);
   AfxMessageBox(cStr);
#endif

AfxDoForAllObjects

Executes the specified iteration function for all objects derived from CObject that have been allocated with new.

void AfxDoForAllObjects(
    void (* pfn)(CObject* pObject, void* pContext),  
    void* pContext); 

Parameters

pfn
Points to an iteration function to execute for each object. The function arguments are a pointer to a CObject and a void pointer to extra data that the caller supplies to the function.

pContext
Points to optional data that the caller can supply to the iteration function. This pointer can be NULL.

Remarks

Stack, global, or embedded objects are not enumerated. The pointer passed to AfxDoForAllObjects in pContext is passed to the specified iteration function each time it is called.

Note

This function works only in the Debug version of MFC.

Example

#ifdef _DEBUG
void DoForAllObjects(CObject* pObject, void* pContext)
{
   int *pnCount = (int*)pContext;

   pObject->AssertValid();
   if (pnCount != NULL)
      (*pnCount)++;
}
#endif // _DEBUG
#ifdef _DEBUG
   //AfxDoForAllObjects will call the function DoForAllObjects 
   //For each CObject-derived object that is allocated on the heap
   int nCount = 0;
   AfxDoForAllObjects(DoForAllObjects, &nCount);
   TRACE("%d Objects Checked\n", nCount);
#endif

See Also

Macros and Globals