今天公司有同事問(wèn)我ASSERT與VERIFY宏有什么區(qū)別,雖然平時(shí)常用這兩個(gè)宏對(duì)一些變量在Debug模式下作判斷,但一時(shí)還真答不上來(lái)二者之間的具體差別,看來(lái)只是知其然不知其所以然。后來(lái)查了一些資料,總算弄清楚了二者之間的區(qū)別,整理后與同事交流了一番,感覺(jué)收獲還是蠻大的。下面對(duì)我的理解進(jìn)行了總結(jié):
1 ASSERT與VERIFY宏在Debug模式下作用基本一致,二者都對(duì)表達(dá)式的值進(jìn)行計(jì)算,如果值為非0,則什么事也不做;如果值為0,則輸出診斷信息。
2 ASSERT與VERIFY宏在Release模式下效果完全不一樣。ASSERT不計(jì)算表達(dá)式的值,也不會(huì)輸出診斷信息;VERIFY計(jì)算表達(dá)式的值,但不管值為0還是非0都不會(huì)輸出診斷信息。
VERIFY 與ASSERT用在程序調(diào)試上并無(wú)本質(zhì)上的區(qū)別。
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() 。事實(shí)上,這些宏都是調(diào)用了 assert() 函數(shù),只不過(guò)附加了一些與庫(kù)有關(guān)的調(diào)試代碼。如果你在這些宏中加入了任何程序代碼,而不只是布爾表達(dá)式(例如賦值、能改變變量值的函數(shù)調(diào)用 等),那么 Release 版都不會(huì)執(zhí)行這些操作,從而造成錯(cuò)誤。初學(xué)者很容易犯這類(lèi)錯(cuò)誤,查找的方法也很簡(jiǎn)單,因?yàn)檫@些宏都已在上面列出,只要利用 VC++ 的 Find in Files 功能在工程所有文件中找到用這些宏的地方再一一檢查即可。另外,有些高手可能還會(huì)加入 #ifdef _DEBUG 之類(lèi)的條件編譯,也要注意一下。
順便值得一提的是
VERIFY() 宏,這個(gè)宏允許你將程序代碼放在布爾表達(dá)式里。這個(gè)宏通常用來(lái)檢查 Windows API 的返回值。有些人可能為這個(gè)原因而濫用 VERIFY() ,事實(shí)上這是危險(xiǎn)的,因?yàn)?VERIFY() 違反了斷言的思想,不能使程序代碼和調(diào)試代碼完全分離,最終可能會(huì)帶來(lái)很多麻煩。因此,專(zhuān)家們建議盡量少用這個(gè)宏。