现在的位置: 首页 > 综合 > 正文

零缺陷编程读书笔记(四)自己设计并使用断言(2)

2014年10月05日 ⁄ 综合 ⁄ 共 1306字 ⁄ 字号 评论关闭

3
利用断言进行补救

说老实话 memcpy中的调试码编得非常蹩脚,且颇有点喧宾夺主的意味。

void memcpy(void* pvTo, void* pvFrom, size_t size)

{

 void* pbTo = (byte*)pvTo;

 void* pbFrom = (byte*)pvFrom;

 assert(pvTo != NULL && pvFrom != NULL);

 while(size-->0)

  *pbTo++ == *pbFrom++;

 return(pvTo);

}

既要维护程序的交付版本又要维护程序的调试版本

aasert
是个只有定义了 DEBUG 才起作用的宏,如果其参数的计算结果为假,就中止
调用程序的执行。因此在上面的程序中任何一个指针为 NULL都会引发 assert

 

assert
并不是一个仓促拼凑起来的宏,为了不在程序的交付版本和调试版本之间引起重

要的差别,需要对其进行仔细的定义。宏 assert不应该弄乱内存,不应该对未初始化的数

据进行初始化,即它不应该产主其他的副作用。正是因为要求程序的调试版本和交付版本行

为完全相同,所以才不把 assert作为函数,而把它作为宏。如果把 assert
作为函数的话,

其调用就会引起不期望的内存或代码的兑换。要记住,使用 assert的程序员是把它看成一

个在任何系统状态下都可以安全使用的无害检测手段。

 

读者还要意识到,一旦程序员学会了使用断言,就常常会对宏 assert进行重定义。例如,程序员可以把 assert
定义成当发生错误时不是中止调用程序的执行,而是在发生错误

的位置转入调试程序。assert的某些版本甚至还可以允许用户选择让程序继续运行,就仿佛

从来没有发生过错误一样。

 

下面是一种用户自己定义宏 ASSERT的方法

#ifdef DEBUG

 void _Assert(char* , unsigned);   /* 原型  */

#define ASSERT(f)    \

if(f) \

NULL; \

else \

  _Assert(__FILE__ , __LINE__)

#else

 #define ASSERT(f)    NULL

#endif

 

void _Assert(char* strFile, unsigned uLine)

{

 fflush(stdout);

 fprintf(stderr, \nAssertion failed: %s, line %u\n ,strFile, uLine);

 fflush(stderr);

 abort();

}

 

现在如果用 NULL指针调用 memcpy ASSERT就会抓住这个错误,并显示出如下的

错误信息:

Assertion failed: string.c , line 153

这给出了 assert ASSERT
之间的另一点不同。

 

不管断言宏最终是用什么样方法定义的,都要使用它来对传递给相应函数的参数进行确

认。如果在函数的每个调用点都对其参数进行检查,错误很快就会被发现。断言宏的最好作

用是使用户在错误发生时,就可以自动地把它们检查出来。

 

要使用断言对函数参数进行确认

 

转载请注明原创连接:http://blog.csdn.net/wujunokay/article/details/17723381

 

抱歉!评论已关闭.