自己实现的assert(断言)程序

来源:互联网 发布:淘宝卖家身份取消 编辑:程序博客网 时间:2024/06/07 16:06

自己实现的asset(断言)程序

1、概况

       很多教科书都叫程序员在编程的时候要进行防错设计,而实际上这也是必要的。防错设计能有效的捕捉到程序运行时出现的非法和错误状态,这样,程序员可以很快的定位错误发送的地方以便进一步处理。很难想象到了一定规模的系统没有防错设计是多么的可怕。有一句很经典的话:不知道不可怕,可怕的是不知道自己不知道。这句话用在这里一样经典:程序出错不可怕,可怕的是不知道出错了。

       防错设计有很多种,比如记录log文件、对话框出错提示等等。今天我要说的防错设计是assert(断言)。

2assert(断言)

       程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。断言assert 是仅在Debug 版本起作用的宏,它用于监测“不应该”发生的情况。为了不在程序的Debug 版本和Release 版本引起差别,assert 不应该产生任何副作用。所以assert 不是函数,而是宏。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。

2.1 各种类型的断言

       CC++都给我们提供了断言:

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、自己实现的“断言”

       笔者在使用断言的时候,更愿意自己定制断言的形式,比如可以定制错误信息是显示在标准的输出屏幕上(类似命令行的窗口),还是显示在弹出对话框中;可以定制错误信息包括的内容:出错的源码文件名,出错的行号,出错的代码,出错的提示信息等等。以下这个宏就是笔者自己定制的一个断言宏。有不妥之处,忘大家指教。

  1. /*
  2. * MyVerify.h
  3. * 自己实现的断言宏——MYVERIFY
  4. * 2008.10.30
  5. * Kaoya
  6. */
  7. #ifndef __MYVERIFY_H__
  8. #define __MYVERIFY_H__
  9. #pragma comment( lib, "USER32" )
  10. #include <crtdbg.h>
  11. #ifdef _DEBUG
  12. #define MYVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
  13. #else
  14. #define MYVERIFY(a)
  15. #endif
  16. __inline void PrintError(LPSTR linedesc, LPSTR filename, int lineno, DWORD errnum)
  17. {
  18.   LPSTR lpBuffer;
  19.   char errbuf[256];
  20.   char modulename[MAX_PATH];
  21.   DWORD numread;
  22.   
  23.   FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
  24.     | FORMAT_MESSAGE_FROM_SYSTEM,
  25.     NULL,
  26.     errnum,
  27.     LANG_NEUTRAL,
  28.     (LPTSTR)&lpBuffer,
  29.     0,
  30.     NULL );
  31.   
  32.   GetModuleFileName(NULL, modulename, MAX_PATH);
  33.   wsprintf(errbuf, "/n%s occur failed at line %d in %s:/n/n"
  34.     "    %s/n/nReason: %s/n", modulename, lineno, filename, linedesc, lpBuffer);
  35.   
  36. #ifndef _WINDOWS
  37.   WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, strlen(errbuf), &numread, FALSE );
  38.   Sleep(3000);
  39. #else
  40.   MessageBox(GetActiveWindow(), errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
  41. #endif
  42.   
  43.   exit(EXIT_FAILURE);
  44. }
  45. #endif//__MYVERIFY_H__

 

 

原创粉丝点击