自己实现的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__