今天公司有同事问我ASSERT与VERIFY宏有什么区别,虽然平时常用这两个宏对一些变量在Debug模式下作判断,但一时还真答不上来二者之间的具体差别,看来只是知其然不知其所以然。后来查了一些资料,总算弄清楚了二者之间的区别,整理后与同事交流了一番,感觉收获还是蛮大的。下面对我的理解进行了总结:
1 ASSERT与VERIFY宏在Debug模式下作用基本一致,二者都对表达式的值进行计算,如果值为非0,则什么事也不做;如果值为0,则输出诊断信息。
2 ASSERT与VERIFY宏在Release模式下效果完全不一样。ASSERT不计算表达式的值,也不会输出诊断信息;VERIFY计算表达式的值,但不管值为0还是非0都不会输出诊断信息。
VERIFY 与ASSERT用在程序调试上并无本质上的区别。
In the debug version of MFC, the VERIFY macro evaluates its argument. If the result is 0,
the macro prints a diagnostic message and halts the program. If the condition is nonzero,
it does nothing.
In the release version of MFC, VERIFY evaluates the expression but does not print or interrupt the program. For example, if the expression is a function call, the call will be made.
ANSI C 断言 |
void assert(int expression ); |
C Runtime Lib 断言 |
_ASSERT( booleanExpression ); _ASSERTE( booleanExpression ); |
MFC 断言 |
ASSERT( booleanExpression ); VERIFY( booleanExpression ); ASSERT_VALID( pObject ); ASSERT_KINDOF( classname, pobject ); |
ATL 断言 |
ATLASSERT( booleanExpression ); |
此外,TRACE() 宏的编译也受 _DEBUG 控制。
所有这些断言都只在 Debug版中才被编译,而在 Release 版中被忽略。唯一的例外是 VERIFY() 。事实上,这些宏都是调用了 assert() 函数,只不过附加了一些与库有关的调试代码。如果你在这些宏中加入了任何程序代码,而不只是布尔表达式(例如赋值、能改变变量值的函数调用 等),那么 Release 版都不会执行这些操作,从而造成错误。初学者很容易犯这类错误,查找的方法也很简单,因为这些宏都已在上面列出,只要利用 VC++ 的 Find in Files 功能在工程所有文件中找到用这些宏的地方再一一检查即可。另外,有些高手可能还会加入 #ifdef _DEBUG 之类的条件编译,也要注意一下。
顺便值得一提的是
VERIFY() 宏,这个宏允许你将程序代码放在布尔表达式里。这个宏通常用来检查 Windows API 的返回值。有些人可能为这个原因而滥用 VERIFY() ,事实上这是危险的,因为 VERIFY() 违反了断言的思想,不能使程序代码和调试代码完全分离,最终可能会带来很多麻烦。因此,专家们建议尽量少用这个宏。