診斷服務
MFC 程式庫提供許多診斷服務,可讓您更輕鬆地對程式進行偵錯。 這些診斷服務包含巨集和全域函式,可讓您追蹤程式的記憶體配置、在執行階段傾印物件的內容,以及在執行階段列印偵錯訊息。 診斷服務的巨集和全域函式可分為下列分類:
一般診斷巨集
一般診斷函式和變數
物件診斷函式
這些巨集和函式都可以在 MFC 的偵錯和發行版本中,供所有衍生自 CObject
的類別使用。 不過,除了DEBUG_NEW和 VERIFY 以外的所有專案,都不會在發行版本中執行任何動作。
在偵錯連結庫中,所有配置的記憶體區塊都會以一系列的「防護位元節」括住。如果這些位元組受到錯誤記憶體寫入的干擾,則診斷例程可能會回報問題。 如果您在實作檔中包含此行:
#define new DEBUG_NEW
在您的實作檔案中,所有對的呼叫 new
都會儲存記憶體配置發生所在的檔名和行號。 CMemoryState::DumpAllObjectsSince 函式會顯示這項額外的資訊,讓您找出記憶體流失的問題。 如需診斷輸出的其他資訊,另請參閱 CDumpContext 類別。
此外,C 執行階段程式庫也支援一組可用來偵錯應用程式的診斷函式。 如需詳細資訊,請參閱<執行階段程式庫參考>中的 偵錯常式 。
MFC 一般診斷巨集
名稱 | 描述 |
---|---|
ASSERT | 如果指定的運算式在程式庫的偵錯版本中評估為 FALSE ,則會列印訊息,再中止程式。 |
ASSERT_KINDOF | 測試物件是指定類別的物件,還是衍生自指定類別之類別的物件。 |
ASSERT_VALID | 藉由呼叫物件的 AssertValid 成員函式來測試其內部有效性,通常會覆寫自 CObject 。 |
DEBUG_NEW | 提供偵錯模式中所有物件配置的檔案名稱和行號,以協助找出記憶體流失的問題。 |
DEBUG_ONLY | 類似於 ASSERT ,但不會測試運算式的值;適用於只能在偵錯模式中執行的程式碼。 |
ENSURE 和 ENSURE_VALID | 使用 來驗證數據正確性。 |
THIS_FILE | 展開至正在編譯的檔名。 |
TRACE | 提供此程式庫之偵錯版本中類似 printf 的功能。 |
VERIFY | 類似於 ASSERT ,但不僅會評估此程式庫之發行版本中的運算式,也會評估偵錯版本中的運算式。 |
MFC 一般診斷變數和函式
名稱 | 描述 |
---|---|
afxDump | 全域變數,可將 CDumpContext 資訊傳送至偵錯工具輸出視窗或偵錯終端機。 |
afxMemDF | 全域變數,可控制偵錯記憶體配置器的行為。 |
AfxCheckError | 全域變數,可用來測試所傳遞的 SCODE 以查看其是否為錯誤;如果是,則擲回適當的錯誤。 |
AfxCheckMemory | 檢查目前配置之所有記憶體的完整性。 |
AfxDebugBreak | 導致執行中斷。 |
AfxDump | 如果在偵錯工具中呼叫,則會一面進行偵錯,一面傾印物件的狀態。 |
AfxDump | 在偵錯時傾印物件狀態的內部函式。 |
AfxDumpStack | 產生目前堆疊的映像。 這個函式一律會以靜態方式連結。 |
AfxEnableMemoryLeakDump | 啟用記憶體流失傾印。 |
AfxEnableMemoryTracking | 開啟和關閉記憶體追蹤。 |
AfxIsMemoryBlock | 確認已適當地配置記憶體區塊。 |
AfxIsValidAddress | 確認記憶體位址範圍落在程式的範圍內。 |
AfxIsValidString | 判斷字串指標是否有效。 |
AfxSetAllocHook | 允許對每個記憶體配置呼叫函式。 |
MFC 物件診斷函式
名稱 | 描述 |
---|---|
AfxDoForAllClasses | 針對所有可支援執行階段類型檢查的 CObject 衍生類別執行指定的函式。 |
AfxDoForAllObjects | 在使用 new 配置的所有CObject 衍生物件上執行指定的函式。 |
MFC 編譯巨集
名稱 | 描述 |
---|---|
_AFX_SECURE_NO_WARNINGS | 隱藏關於使用被取代 MFC 的功能的編譯器警告。 |
_AFX_SECURE_NO_WARNINGS
隱藏關於使用被取代 MFC 的功能的編譯器警告。
語法
_AFX_SECURE_NO_WARNINGS
範例
如果未定義,此程式代碼範例會造成編譯程式警告 _AFX_SECURE_NO_WARNINGS
。
// define this before including any afx files in *pch.h* (*stdafx.h* in Visual Studio 2017 and earlier)
#define _AFX_SECURE_NO_WARNINGS
// . . .
CRichEditCtrl* pRichEdit = new CRichEditCtrl;
pRichEdit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE,
CRect(10,10,100,200), pParentWnd, 1);
char sz[256];
pRichEdit->GetSelText(sz);
AfxDebugBreak
呼叫此函式,以在執行 MFC 應用程式的偵錯版本時造成中斷(在呼叫 AfxDebugBreak
的位置)。
語法
void AfxDebugBreak( );
備註
AfxDebugBreak
在 MFC 應用程式的發行版本中沒有作用,因此應該移除。 此函式只應用於 MFC 應用程式中。 使用 Win32 API 版本 DebugBreak
,在非 MFC 應用程式中造成中斷。
需求
標頭: afxver_.h
ASSERT
評估其自變數。
ASSERT(booleanExpression)
參數
booleanExpression
指定評估為非零或 0 的運算式(包括指標值)。
備註
如果結果為 0,巨集會列印診斷訊息並中止程式。 如果條件為非零,則不會執行任何動作。
診斷資訊的格式如下
assertion failed in file <name> in line <num>
其中 name 是來源檔案的名稱,而 num 是來源檔案中失敗之判斷提示的行號。
在 MFC 的 Release 版本中,ASSERT 不會評估表達式,因此不會中斷程式。 如果不論環境為何,都必須評估表達式,請使用 VERIFY 巨集取代 ASSERT。
注意
此函式僅適用於 MFC 的偵錯版本。
範例
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*.
需求
標頭: afx.h
ASSERT_KINDOF
這個巨集判斷提示指向的物件是指定類別的物件,或是衍生自指定類別之類別的物件。
ASSERT_KINDOF(classname, pobject)
參數
classname
衍生類別 CObject
的名稱。
pobject
類別物件的指標。
備註
pobject 參數應該是 物件的指標,而且可以是 const
。 指向的物件和 類別必須支援 CObject
運行時間類別資訊。 例如,若要確保 pDocument
是 類別物件的 CMyDoc
指標,或其任何衍生專案,您可以撰寫下列程序代碼:
ASSERT_KINDOF(CMyDoc, pDocument);
ASSERT_KINDOF
使用巨集與撰寫程式代碼完全相同:
ASSERT(pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
此函式僅適用於以 [DECLARE_DYNAMIC] 宣告的類別(run-time-object-model-services.md#declare_dynamic 或 DECLARE_SERIAL 巨集。
注意
此函式僅適用於 MFC 的偵錯版本。
需求
標頭: afx.h
ASSERT_VALID
使用 來測試有關對象內部狀態有效性的假設。
ASSERT_VALID(pObject)
參數
pObject
指定衍生自 CObject
且具有覆寫成員函式版本的 AssertValid
類別物件。
備註
ASSERT_VALID呼叫 AssertValid
做為其自變數傳遞之對象的成員函式。
在 MFC 的發行版本中,ASSERT_VALID不會執行任何動作。 在偵錯版本中,它會驗證指標、檢查 NULL,以及呼叫物件自己的 AssertValid
成員函式。 如果其中任何一項測試失敗,警示訊息會以與 ASSERT相同的方式顯示。
注意
此函式僅適用於 MFC 的偵錯版本。
如需詳細資訊和範例,請參閱 偵錯 MFC 應用程式。
範例
// Assure that pMyObject is a valid pointer to an
// object derived from CObject.
ASSERT_VALID(pMyObject);
需求
標頭: afx.h
DEBUG_NEW
協助尋找記憶體流失。
#define new DEBUG_NEW
備註
您可以在程式中的任何地方使用DEBUG_NEW,您通常會使用 new
運算符來配置堆積記憶體。
在偵錯模式中(定義_DEBUG符號時),DEBUG_NEW會追蹤其配置之每個物件的檔名和行號。 然後,當您使用 CMemoryState::D umpAllObjectsSince 成員函式時,配置DEBUG_NEW的每個物件都會以配置所在的檔名和行號來顯示。
若要使用DEBUG_NEW,請將下列指示詞插入原始程式檔中:
#define new DEBUG_NEW
插入此指示詞之後,預處理器會在您使用 new
的位置插入DEBUG_NEW,而 MFC 會執行其餘作業。 當您編譯程式的發行版本時,DEBUG_NEW解析為簡單的 new
作業,而且不會產生檔名和行號資訊。
注意
在舊版的 MFC (4.1 和更早版本中),您需要將所有稱為IMPLEMENT_DYNCREATE或IMPLEMENT_SERIAL巨集的語句放在 #define
後面。 但目前已經不是必要的了。
需求
標頭: afx.h
DEBUG_ONLY
在偵錯模式中(定義_DEBUG符號時),DEBUG_ONLY評估其自變數。
DEBUG_ONLY(expression)
備註
在發行組建中,DEBUG_ONLY不會評估其自變數。 當您的程式代碼應該只在偵錯組建中執行時,這會很有用。
DEBUG_ONLY巨集相當於搭配和 #ifdef _DEBUG
#endif
的周圍表達式。
範例
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');
}
需求
標頭: afx.h
ENSURE 和 ENSURE_VALID
使用 來驗證數據正確性。
語法
ENSURE( booleanExpression )
ENSURE_VALID( booleanExpression )
參數
booleanExpression
指定要測試的布爾表達式。
備註
這些巨集的目的是要改善參數的驗證。 巨集可防止在程式碼中進一步處理不正確的參數。 不同於 ASSERT 巨集,ENSURE 巨集除了產生判斷提示之外,也會擲回例外狀況。
巨集的行為有兩種方式,根據項目組態。 巨集會呼叫 ASSERT,然後在判斷提示失敗時擲回例外狀況。 因此,在偵錯組態中(也就是定義_DEBUG的位置)巨集會在發行組態中產生判斷提示和例外狀況,巨集只會產生例外狀況(ASSERT 不會評估 Release 組態中的表達式)。
巨集ENSURE_ARG的作用就像 ENSURE 巨集一樣。
ENSURE_VALID會呼叫ASSERT_VALID巨集(只有在偵錯組建中才會有效果)。 此外,如果指標為 NULL,ENSURE_VALID會擲回例外狀況。 NULL 測試會在偵錯和發行組態中執行。
如果其中任何一項測試失敗,警示訊息會以與ASSERT相同的方式顯示。 如有需要,巨集會擲回無效的自變數例外狀況。
需求
標頭: afx.h
THIS_FILE
展開至正在編譯的檔名。
語法
THIS_FILE
備註
資訊是由 ASSERT 和 VERIFY 巨集使用。 應用程式精靈和程式代碼精靈會將巨集放在他們建立的原始碼檔案中。
範例
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// __FILE__ is one of the six predefined ANSI C macros that the
// compiler recognizes.
需求
標頭: afx.h
TRACE
將指定的字串傳送至目前應用程式的調試程式。
TRACE(exp)
TRACE(DWORD category, UINT level, LPCSTR lpszFormat, ...)
備註
如需 TRACE 的描述,請參閱ATLTRACE2。 TRACE 和 ATLTRACE2具有相同的行為。
在 MFC 的偵錯版本中,這個巨集會將指定的字串傳送至目前應用程式的調試程式。 在發行組建中,此巨集不會編譯成任何專案(完全不會產生任何程序代碼)。
如需詳細資訊,請參閱 偵錯 MFC 應用程式。
需求
標頭: afx.h
VERIFY
在 MFC 的偵錯版本中,評估其自變數。
VERIFY(booleanExpression)
參數
booleanExpression
指定評估為非零或 0 的運算式(包括指標值)。
備註
如果結果為 0,巨集會列印診斷訊息並停止程式。 如果條件為非零,則不會執行任何動作。
診斷資訊的格式如下
assertion failed in file <name> in line <num>
其中 name 是來源檔案的名稱, 而 num 是來源檔案中失敗之判斷提示的行號。
在 MFC 的發行版本中,VERIFY 會評估表達式,但不會列印或中斷程式。 例如,如果表達式是函數調用,則會進行呼叫。
範例
// 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);
需求
標頭: afx.h
afxDump (MFC 中的 CDumpContext)
在您的應用程式中提供基本的物件傾印功能。
CDumpContext afxDump;
備註
afxDump
是預先定義的 CDumpContext 物件,可讓您將資訊傳送 CDumpContext
至調試程式輸出視窗或偵錯終端機。 一般而言,您會將 做為 的參數CObject::Dump
提供給 afxDump
。
在 Windows NT 和所有版本的 Windows 下,當您偵錯應用程式時, afxDump
輸出會傳送至 Visual C++的 [輸出偵錯] 視窗。
此變數只會在 MFC 的偵錯版本中定義。 如需 的詳細資訊 afxDump
,請參閱 偵錯 MFC 應用程式。
範例
// 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
需求
標頭: afx.h
AfxDump (內部)
MFC 在偵錯時用來傾印物件狀態的內部函式。
語法
void AfxDump(const CObject* pOb);
參數
pOb
衍生自 CObject
之類別物件的指標。
備註
AfxDump
會呼叫對象的 Dump
成員函式,並將資訊傳送至變數所 afxDump
指定的位置。 AfxDump
僅適用於 MFC 的偵錯版本。
您的程式代碼不應該呼叫 AfxDump
,但應該改為呼叫 Dump
適當對象的成員函式。
需求
標頭: afx.h
afxMemDF
此變數可從調試程式或程式存取,並可讓您微調配置診斷。
int afxMemDF;
備註
afxMemDF
可以具有列舉所 afxMemDF
指定的下列值:
allocMemDF
開啟偵錯配置器 (偵錯連結庫中的預設設定)。delayFreeMemDF
延遲釋放記憶體。 當程式釋放記憶體區塊時,配置器不會將該記憶體傳回基礎操作系統。 這會將記憶體壓力上限放在您的程式上。checkAlwaysMemDF
每次配置或釋放記憶體時呼叫AfxCheckMemory
。 這會大幅降低記憶體配置和解除分配的速度。
範例
afxMemDF = allocMemDF | checkAlwaysMemDF;
需求
標頭: afx.h
AfxCheckError
此函式會測試通過的 SCODE,以查看其是否為錯誤。
void AFXAPI AfxCheckError(SCODE sc);
throw CMemoryException*
throw COleException*
備註
如果是錯誤,函式會擲回例外狀況。 如果傳遞的 SCODE 是E_OUTOFMEMORY,函式會呼叫 AfxThrowMemoryException 來擲回 CMemoryException。 否則,函式會呼叫 AfxThrowOleException 來擲回 COleException。
這個函式可用來檢查對應用程式中 OLE 函式呼叫的傳回值。 藉由在應用程式中以此函式測試傳回值,您可以用最少的程式碼因應錯誤狀況。
注意
這個函式在偵錯和非偵錯組建中具有相同的效果。
範例
AfxCheckError(::CoCreateInstance(clsidWMP, NULL, CLSCTX_INPROC_SERVER,
IID_IDispatch, (LPVOID*)& pWMPDispatch));
oddWMP.AttachDispatch(pWMPDispatch, TRUE);
需求
標頭: afx.h
AfxCheckMemory
此函式會驗證可用的記憶體集區,並視需要列印錯誤訊息。
BOOL AfxCheckMemory();
傳回值
如果沒有記憶體錯誤,則為非零;否則為 0。
備註
如果函式未偵測到記憶體損毀,則不會列印任何內容。
會檢查堆積上目前配置的所有記憶體區塊,包括 由 new
配置但不是由直接呼叫基礎記憶體配置器所配置的記憶體區塊,例如 malloc 函式或 GlobalAlloc
Windows 函式。 如果發現有任何區塊損毀,則會將訊息列印至調試程序輸出。
如果您包含這一行
#define new DEBUG_NEW
在程式模組中,接著會呼叫 ,以顯示 AfxCheckMemory
配置記憶體的檔名和行號。
注意
如果您的模組包含一或多個可串行化類別的實作,則必須將這一行放在 #define
最後一個IMPLEMENT_SERIAL巨集呼叫之後。
此函式僅適用於 MFC 的偵錯版本。
範例
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();
需求
標頭: afx.h
AfxDump (MFC)
在調試程式中呼叫此函式,以在偵錯時傾印物件的狀態。
void AfxDump(const CObject* pOb);
參數
pOb
衍生自 CObject
之類別物件的指標。
備註
AfxDump
會呼叫對象的 Dump
成員函式,並將資訊傳送至變數所 afxDump
指定的位置。 AfxDump
僅適用於 MFC 的偵錯版本。
您的程式代碼不應該呼叫 AfxDump
,但應該改為呼叫 Dump
適當對象的成員函式。
需求
標頭: afx.h
AfxDumpStack
這個全域函式可用來產生目前堆疊的影像。
void AFXAPI AfxDumpStack(DWORD dwTarget = AFX_STACK_DUMP_TARGET_DEFAULT);
參數
dwTarget
表示傾印輸出的目標。 可以使用位 OR (|
) 運算子結合的可能值如下所示:
AFX_STACK_DUMP_TARGET_TRACE透過 TRACE 巨集傳送輸出。 TRACE 巨集只會在偵錯組建中產生輸出;它不會在發行組建中產生任何輸出。 此外,除了調試程式之外,TRACE 也可以重新導向至其他目標。
AFX_STACK_DUMP_TARGET_DEFAULT將傾印輸出傳送至預設目標。 針對偵錯組建,輸出會移至 TRACE 巨集。 在發行組建中,輸出會移至剪貼簿。
AFX_STACK_DUMP_TARGET_CLIPBOARD僅將輸出傳送至剪貼簿。 數據會使用剪貼簿格式的CF_TEXT純文字放在剪貼簿上。
AFX_STACK_DUMP_TARGET_BOTH同時將輸出傳送至剪貼簿和 TRACE 巨集。
AFX_STACK_DUMP_TARGET_ODS 透過 Win32 函式
OutputDebugString()
直接將輸出傳送至調試程式。 當調試程式附加至進程時,此選項會在偵錯和發行組建中產生調試程序輸出。 AFX_STACK_DUMP_TARGET_ODS一律會到達調試程式(如果已附加),而且無法重新導向。
備註
下列範例會反映從 MFC 對話框應用程式中的按鈕處理程式呼叫 AfxDumpStack
所產生的輸出單行:
=== 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 ===
上述輸出中的每個行都會指出最後一個函數調用的位址、包含函數調用之模組的完整路徑名稱,以及呼叫的函式原型。 如果堆疊上的函式呼叫未在函式的確切位址發生,則會顯示位元移。
例如,下表描述上述輸出的第一行:
輸出 | 描述 |
---|---|
00427D55: |
最後一個函式呼叫的傳回位址。 |
DUMP2\DEBUG\DUMP2.EXE! |
包含函數調用之模組的完整路徑名稱。 |
void AfxDumpStack(unsigned long) |
呼叫的函式原型。 |
+ 181 bytes |
從函式原型位址(在此案例中為 void AfxDumpStack(unsigned long) )到傳回位址的位元移(在此案例中為 00427D55 )。 |
AfxDumpStack
適用於 MFC 連結庫的偵錯和非偵錯版本;不過,即使可執行檔在共用 DLL 中使用 MFC,函式一律會以靜態方式連結。 在共用連結庫實作中,函式可在 MFCS42 中找到。LIB 連結庫(及其變體)。
若要成功使用此函式:
檔案IMAGEHLP.DLL必須位於您的路徑上。 如果您沒有此 DLL,函式會顯示錯誤訊息。 如需 IMAGEHLP 所提供的函式集資訊,請參閱 影像說明連結庫 。
堆疊上具有框架的模組必須包含偵錯資訊。 如果沒有包含偵錯資訊,函式仍會產生堆疊追蹤,但追蹤會較不詳細。
需求
標頭: afx.h
AfxEnableMemoryLeakDump
啟用和停用AFX_DEBUG_STATE解構函式中的記憶體流失傾印。
BOOL AFXAPI AfxEnableMemoryLeakDump(BOOL bDump);
參數
bDump
[in]TRUE 表示已啟用記憶體流失轉儲;FALSE 表示記憶體流失傾印已停用。
傳回值
此旗標先前的值。
備註
當應用程式卸載 MFC 程式庫時,MFC 程式庫會檢查記憶體流失。 此時,任何記憶體流失會透過 Visual Studio的 [偵錯] 視窗回報給使用者。
如果您的應用程式在 MFC 程式庫之前先載入另一個程式庫,系統會將該程式庫中的一些記憶體配置誤報為記憶體流失。 因為 MFC 程式庫發生記憶體流失誤報的情況,這些誤報可能會導致您的應用程式關閉速度很慢。 在這種情況下,請使用 AfxEnableMemoryLeakDump
以停用記憶體流失傾印。
注意
如果您使用這個方法來關閉記憶體流失傾印,就不會收到應用程式中有效的記憶體流失報告。 因此,僅有當您確信記憶體流失報告包含誤報的記憶體流失,才建議使用這個方法。
需求
標頭: afx.h
AfxEnableMemoryTracking
診斷記憶體追蹤通常會在 MFC 的偵錯版本中啟用。
BOOL AfxEnableMemoryTracking(BOOL bTrack);
參數
bTrack
將此值設定為TRUE 會開啟記憶體追蹤;FALSE 將其關閉。
傳回值
追蹤啟用旗標的上一個設定。
備註
使用此函式來停用您知道正確配置區塊的程式代碼區段追蹤。
如需 的詳細資訊 AfxEnableMemoryTracking
,請參閱 偵錯 MFC 應用程式。
注意
此函式僅適用於 MFC 的偵錯版本。
範例
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;
}
需求
標頭: afx.h
AfxIsMemoryBlock
測試記憶體位址,以確定它代表診斷版本 new
所配置的目前使用中記憶體區塊。
BOOL AfxIsMemoryBlock(
const void* p,
UINT nBytes,
LONG* plRequestNumber = NULL);
參數
p
指向要測試的記憶體區塊。
nBytes
包含以位元組為單位的記憶體區塊長度。
plRequestNumber
long
指向將填入記憶體區塊配置序號的整數,如果它不代表目前作用中的記憶體區塊,則為零。
傳回值
如果記憶體區塊目前已配置且長度正確,則為非零;否則為 0。
備註
它也會根據原始配置的大小檢查指定的大小。 如果函式傳回非零,則會在 plRequestNumber 中傳回配置序號。 這個數位代表區塊相對於所有其他 new
配置配置的順序。
範例
CAge* pcage = new CAge(21); // CAge is derived from CObject.
ASSERT(AfxIsMemoryBlock(pcage, sizeof(CAge)));
需求
標頭: afx.h
AfxIsValidAddress
測試任何記憶體位址,以確保它完全包含在程式的記憶體空間內。
BOOL AfxIsValidAddress(
const void* lp,
UINT nBytes,
BOOL bReadWrite = TRUE);
參數
lp
指向要測試的記憶體位址。
nBytes
包含要測試的記憶體位元組數目。
bReadWrite
指定記憶體是用於讀取和寫入 (TRUE) 還是只讀取 (FALSE)。
傳回值
在偵錯組建中,如果指定的記憶體區塊完全包含在程式的記憶體空間內,則為非零;否則為 0。
在非偵錯組建中,如果 lp 不是 NULL,則為非零,否則為 0。
備註
位址不限於 所 new
配置的區塊。
範例
// 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));
需求
標頭: afx.h
AfxIsValidString
使用此函式來判斷字串的指標是否有效。
BOOL AfxIsValidString(
LPCSTR lpsz,
int nLength = -1);
參數
lpsz
要測試的指標。
nLength
指定要測試的字串長度,以位元組為單位。 值 -1 表示字串會以 Null 結束。
傳回值
在偵錯組建中,如果指定的指標指向指定大小的字串,則為非零;否則為 0。
在非偵錯組建中,如果 lpsz 不是 NULL,則為非零,否則為 0。
範例
// 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));
需求
標頭: afx.h
AfxSetAllocHook
設定勾點,可在配置每個記憶體區塊之前呼叫指定的函式。
AFX_ALLOC_HOOK AfxSetAllocHook(AFX_ALLOC_HOOK pfnAllocHook);
參數
pfnAllocHook
指定要呼叫的函式名稱。 如需配置函式的原型,請參閱。
傳回值
如果您想要允許配置,則為非零;否則為 0。
備註
Microsoft Foundation Class Library debug-memory 配置器可以呼叫使用者定義的攔截函式,讓使用者監視記憶體配置,以及控制是否允許配置。 設定攔截函式的原型如下:
BOOL AFXAPI AllocHook(size_t,BOOL,LONG bObject
nSize
lRequestNumber
):
nSize
建議記憶體配置的大小。
bObject
如果配置是針對衍生的物件,則為TRUE,否則為 CObject
FALSE。
lRequestNumber
記憶體配置的序號。
請注意,AFXAPI 呼叫慣例表示被呼叫者必須從堆疊中移除參數。
需求
標頭: afx.h
AfxDoForAllClasses
針對應用程式記憶體空間中的所有可 CObject
串行化衍生類別,呼叫指定的反覆專案函式。
void
AFXAPI AfxDoForAllClasses(
void (* pfn)(const CRuntimeClass* pClass, void* pContext),
void* pContext);
參數
pfn
指向要針對每個類別呼叫的反覆專案函式。 函式自變數是 物件的指標 CRuntimeClass
,以及呼叫端提供給函式的額外數據的 void 指標。
pContext
指向呼叫端可以提供給反覆專案函式的選擇性數據。 此指標可以是 NULL。
備註
可 CObject
串行化衍生類別是使用 DECLARE_SERIAL 巨集衍生的類別。 在 pContext 中傳遞至 AfxDoForAllClasses
的指標會在每次呼叫時傳遞至指定的反覆專案函式。
注意
此函式僅適用於 MFC 的偵錯版本。
範例
#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
需求
標頭: afx.h
AfxDoForAllObjects
針對已使用 new
配置的所有衍生自 CObject
的物件執行指定的反覆專案函式。
void AfxDoForAllObjects(
void (* pfn)(CObject* pObject, void* pContext),
void* pContext);
參數
pfn
指向要針對每個物件執行的反覆專案函式。 函式自變數是 的 CObject
指標,而 void 指標指向呼叫端提供給函式的額外數據。
pContext
指向呼叫端可以提供給反覆專案函式的選擇性數據。 此指標可以是 NULL。
備註
不會列舉堆疊、全域或內嵌物件。 在 pContext 中傳遞至 AfxDoForAllObjects
的指標會在每次呼叫時傳遞至指定的反覆專案函式。
注意
此函式僅適用於 MFC 的偵錯版本。
範例
#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