使用斷言
12.用MFC時選擇ASSERT宏
13.不要使用VERIFY宏,使用斷言宏
14.在使用CObject衍生類別的對象之前都要調用ASSERT_VALID宏
15.總是在調用ASSERT_KINDOF宏之前調用ASSERT_VALID宏
16.移植代碼的時候也移植斷言
17.要想有效利用斷言需要一定的策略,不要隨意的把斷言分布到你的代碼裡面,而是遵從某些已經建立起來的模式
18."Assert the word",是說:不要試圖選擇哪一個斷言要發現錯誤,而是根據你的斷言策略斷言一切
19.最有力的斷言是用來驗證變數之間的固定關係。這些關係稱為不變關係(invariants)。其中,類不變關係和迴圈不變關係最為普遍
20.設計程式的同時就設計不變關係,在寫代碼之前理解它們,並且為它們建立文檔
21.公有成員函數比私人和保護成員函數需要更全面的斷言
22.充分實現AssertValid函數,不要使用MFC ClassWizard提供的預設實現
23.建議對AssertValid函數採用下面的斷言模式:
void CMyObject::AssertValid()
{
// check the immediate base class first
CMyObjectBaseClass::AssertValid();
// check the data members not in the base class
ASSERT_VALID(m_pObject1);
ASSERT_VALID(m_pObject2);
// now check the class invariants not checked by the base class
// be sure to document the invariants
ASSERT(m_Value != illegalValue);
ASSERT(m_Object1.GetSize() == m_Size);
...
}
24.不正確的使用斷言會導致錯誤。斷言是用來揭示錯誤的,而不是用來糾正運行時刻錯誤的。
25.如果你的程式是防禦性的,別忘了使用斷言。如果你使用斷言,也別忘了防禦性編程。這兩種技術最好結合在一起使用。
26.考慮使用_ASSERTE(FALSE)來簡化防禦性的編程和斷言的結合。要想得到更有描述性的斷言資訊,考慮使用_ASSERTE("Problem description." == 0)。
27.斷言不是錯誤處理的替代品。
28.這種方法讓你不用打擾視窗畫圖就可以在出現視窗後,隨時察看導致斷言失效的代碼。
void CMyview::OnDraw (CDC* pDC) {
int previousReportMode = _CrtSetReportMode(_CRT_ASSERT,
_CRTDBG_MODE_DEBUG):
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
... // draw the window
if (previousReportMode != -1)
_CrtSetReportMode(_CRT_ASSERT,previousReportMode);
}
29.使用GetObjectType函數來斷言一個具有有效控制代碼的GDI對象(察看傳回值是否為零),或者某個特定的GDI對象(察看傳回值是否是某個特殊值)。eg:
_ASSERT(GetObjectType(hBrush) == OBJ_BRUSH);
但是,要意識到GetObjectType函數可能返回一些讓人吃驚的結果。如,下面的斷言失效:
HBRUSH hBrush = CreateSolidBrush(RGB(0,0,0));
DeleteObject(hBrush);
_ASSERTE(GetObjectType(hBrush) == OBJ_BRUSH);
因為黑色的刷子是一個備用裝置的對象(也就是不能刪除),因此 DeleteObject 函數調用就沒有作用。
30.MSDN文檔聲稱IsBadCodePtr、IsBadReadPtr、IsBadStringPtr和IsBadWritePtr這幾個API函數在接收到壞指標的時候就會在調試版本裡導致斷言失效。這個說法是錯誤的,必須把這些函數封裝在Assert 陳述式中。