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