MFC 大量使用 `ASSERT` 宏在 Debug 版本執行期檢查前置條件、不變量與後置條件。`ASSERT(expr)` 若 `expr` 為假 (0/NULL),彈出「Assertion Failed」對話框,顯示檔案名、行號與運算式,提供中斷/繼續/忽略選項。本文解析 `ASSERT` 原理、MFC 內部使用範例與正確使用姿勢。
// 簡化版定義 (afx.h)
#ifdef _DEBUG
#define ASSERT(f) \
do { if (!(f)) AfxAssertFailedLine(THIS_FILE, __LINE__); } while (0)
#else
#define ASSERT(f) ((void)0)
#endif
// CWnd::Attach - 確保尚未附加視窗
BOOL CWnd::Attach(HWND hWndNew) {
ASSERT(m_hWnd == NULL); // 只能 Attach 一次
// ...
}
// CString::AllocBuffer - 長度合法性
void CString::AllocBuffer(int nLen) {
ASSERT(nLen >= 0);
ASSERT(nLen <= INT_MAX - 1);
}
// CDocument::AddView - 視圖未關聯文檔、未在列表中
void CDocument::AddView(CView* pView) {
ASSERT(pView->m_pDocument == NULL);
ASSERT(m_viewList.Find(pView, NULL) == NULL);
}
Assertion Failed! File: d:\proj\mymfc\view.cpp Line: 123 Expression: pView->m_pDocument == NULL
選項:Retry (中斷進入除錯器)、Ignore (繼續執行)、Abort (終止程式)。
| 宏 | Debug | Release | 用途 |
|---|---|---|---|
| ASSERT(expr) | 檢查並中斷 | 無 | 純邏輯檢查 |
| VERIFY(expr) | 檢查並中斷 | 執行 expr | API 呼叫、有副作用運算 |
| ASSERT_VALID(pObj) | 呼叫 pObj->AssertValid() | 無 | 檢查 CObject 衍生類內部狀態 |
| ASSERT_KINDOF(class, pObj) | 檢查 pObj 是否 class 類別 | 無 | 執行期型別安全 |