自己實現的asset(斷言)程式
1、概況
很多教科書都叫程式員在編程的時候要進行防錯設計,而實際上這也是必要的。防錯設計能有效捕捉到程式運行時出現的非法和錯誤狀態,這樣,程式員可以很快的定位錯誤發送的地方以便進一步處理。很難想象到了一定規模的系統沒有防錯設計是多麼的可怕。有一句很經典的話:不知道不可怕,可怕的是不知道自己不知道。這句話用在這裡一樣經典:程式出錯不可怕,可怕的是不知道出錯了。
防錯設計有很多種,比如記錄log檔案、對話方塊出錯提示等等。今天我要說的防錯設計是assert(斷言)。
2、assert(斷言)
程式一般分為Debug 版本和Release 版本,Debug 版本用於內部調試,Release 版本發行給使用者使用。斷言assert 是僅在Debug 版本起作用的宏,它用於監測“不應該”發生的情況。為了不在程式的Debug 版本和Release 版本引起差別,assert 不應該產生任何副作用。所以assert 不是函數,而是宏。程式員可以把assert看成一個在任何系統狀態下都可以安全使用的無害測試手段。
2.1 各種類型的斷言
C和C++都給我們提供了斷言:
◆ANSI C斷言:assert函數。
◆C運行時刻函數庫斷言:_ASSERT宏和_ASSERTE宏。
◆MFC庫的斷言:ASSERT 宏、_ASSERT 宏、VERIFY宏、ASSERT_VALID宏、ASSERT_KINDOF宏、ASSERT_POINTER宏和ASSERT_NULL_OR_POINTER宏。
◆ATL斷言:ATLASSERT
今天我詳細介紹這些斷言的使用方法,大家可以自己去網上查詢。
2.2 斷言的使用
斷言是用來監測錯誤的,不是用來糾正錯誤。我們應該帶著防禦性、檢測性地使用斷言。比如函數參數的合法性(有效性)檢查,API函數調用傳回值的正確性檢查等。
3、自己實現的“斷言”
筆者在使用斷言的時候,更願意自己定製斷言的形式,比如可以定製錯誤資訊是顯示在標準的輸出螢幕上(類似命令列的視窗),還是顯示在彈出對話方塊中;可以定製錯誤資訊包括的內容:出錯的源碼檔案名稱,出錯的行號,出錯的代碼,出錯的提示資訊等等。以下這個宏就是筆者自己定製的一個斷言宏。有不妥之處,忘大家指教。
- /*
- * MyVerify.h
- * 自己實現的斷言宏——MYVERIFY
- * 2008.10.30
- * Kaoya
- */
- #ifndef __MYVERIFY_H__
- #define __MYVERIFY_H__
- #pragma comment( lib, "USER32" )
- #include <crtdbg.h>
- #ifdef _DEBUG
- #define MYVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
- #else
- #define MYVERIFY(a)
- #endif
- __inline void PrintError(LPSTR linedesc, LPSTR filename, int lineno, DWORD errnum)
- {
- LPSTR lpBuffer;
- char errbuf[256];
- char modulename[MAX_PATH];
- DWORD numread;
-
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- errnum,
- LANG_NEUTRAL,
- (LPTSTR)&lpBuffer,
- 0,
- NULL );
-
- GetModuleFileName(NULL, modulename, MAX_PATH);
- wsprintf(errbuf, "/n%s occur failed at line %d in %s:/n/n"
- " %s/n/nReason: %s/n", modulename, lineno, filename, linedesc, lpBuffer);
-
- #ifndef _WINDOWS
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, strlen(errbuf), &numread, FALSE );
- Sleep(3000);
- #else
- MessageBox(GetActiveWindow(), errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
- #endif
-
- exit(EXIT_FAILURE);
- }
- #endif//__MYVERIFY_H__