ASSERT函式

weixin_34377065發表於2014-06-06
 
assert巨集的原型定義在<assert.h>中,其作用是假設它的條件返回錯誤,則終止程式執行,原型定義: 
#include <assert.h> 
void assert( int expression ); 

assert的作用是現計算表示式 expression ,假設其值為假(即為0),那麼它先向stderr列印一條出錯資訊, 
然後通過呼叫 abort 來終止程式執行。 

http://www.chongtang.me/index.php/1419

提高程式健壯性之assert使用

編寫能正常執行的程式非常難;編寫在錯誤情況下仍然表現的非常“優雅”的程式更難。這篇文章將和大家討論一些程式設計技巧,能夠使我們在執行中的程式中早點發現錯誤,檢測和從問題中恢復。那就先討論下斷言(assert)的使用吧。

在編碼時,有一個好的目標應該時刻銘記在心,那就是:應該想辦法讓bug或者異常錯誤儘早使得程式down掉,或者出現錯誤。由於這樣能夠幫助你在開發和測試階段儘快找出bug。有一些錯誤不會無緣無故的暴露自己,往往是產品都到了客戶手上,這些錯誤才會顯現出來。

一個最簡單的檢查異常條件的方法是使用標準C的assert巨集,它的引數是一個bool表示式。當表示式為假時,程式會退出。在退出之前列印錯誤訊息,包含原始檔,行號,和表示式本身。斷言很實用,它提供了一個作用於程式內部的廣泛的一致性檢查方法。比如,使用斷言測試函式引數的有效性,測試異常的返回值等等。

每個斷言的使用不僅提供了一個程式執行時的條件檢查,也像一個對原始碼級別的程式操作的說明性文件。假設你的程式包括了一個斷言,也就是告訴那些閱讀你原始碼的人,在你的原始碼中,在程式的這一點,這個條件應該為真,假設不為真,那就是一個bug。

當然,在追求效能的程式碼中,使用assert會減少程式效能。可是你放心,在編譯時添�NDEBUG引數編譯器就能夠對assert進行預處理,從而移除它。正由於在預處理時可能移除assert,那你使用時就得小心了。什麼時候用,什麼時候不用就成了一個問題。通常,你不應該在assert內部呼叫函式,定義變數,或者使用改變值的操作符,如++。

我們如果你這樣使用了:

for (i = 0; i &lt;= 100; ++i) assert (do_something () == 0);

然後,你可能會發現這樣會使得效能大大減少,從而在創新編譯使使用NDEGUG引數。這將移除整個assert巨集,這就將do_something( )也被移除了,再也不被呼叫。為了糾正錯誤,你應該這樣寫:

for (i = 0; i &lt;= 100; ++i) { int status = do_something (); assert (status == 0); }

另外應該銘記在心的是,不要用assert去檢查無效的輸入。使用者可不喜歡自己在輸入時程式直接退出,即便是輸入錯誤,程式最好也有友好的響應。所以,你應該對無效輸入進行檢查,並輸出一些實用的提示資訊。僅僅在程式執行中進行內部檢查時使用斷言。

在這裡,我會給出一些比較好的在程式中使用assert的地方:

(1)空指標檢查。比如,針對一個函式的引數進行空指標檢查。你能夠這樣使用:assert (pointer != NULL);,產生的錯誤會像這樣:Assertion ‘pointer != ((void *)0)’ failed。這樣,當出現空指標時,你的程式就會退出,並不是常好的給出錯誤資訊。

(2)檢查函式引數的值。比如,假設一個函式僅僅能在它的一個引數foo為正值的時候被呼叫,你能夠在函式開始時這樣寫:assert (foo > 0);,這將幫助你檢測函式的錯誤使用,這也給原始碼閱讀者非常清晰的印象,那就是在這裡對函式的引數值有限制。

說了這麼多,行動起來吧,大膽的在你的程式中使用斷言。



---------------------------------------------------------------   

ASSERT()是一個除錯程式時常常使用的巨集,在程式執行時它計算括號內的表示式,假設表示式為FALSE  (0),  程式將報告錯誤,並終止執行。假設表示式不為0,則繼續執行後面的語句。這個巨集通常原來推斷程式中是否出現了明顯非法的資料,假設出現了終止程式以免導致嚴重後果,同一時候也便於查詢錯誤。   

ASSERT僅僅有在Debug版本號中才有效,假設編譯為Release版本號則被忽略。   
---------------------------------------------------------------   

ASSERT巨集定義例如以下   

#define  ASSERT(f)  \   
do  \   
{  \   
      if  (!(f)  &&  AfxAssertFailedLine(THIS_FILE,  __LINE__))  \   
              AfxDebugBreak();  \   
}  while  (0)  \   

ASSERT(邏輯表示式)   

假設括號裡的邏輯表示式值為假的話,會彈出除錯命令窗體,提示詳細在哪個檔案的哪一行發生了斷言錯誤!   
---------------------------------------------------------------   

ASSERT   
Evaluates  an  expression,  and  displays  a  diagnostic  message  if  the  expression  is  FALSE.  Ignored  in  retail  builds.   

Syntax   

ASSERT(   
      cond   
);   

Parameters   

cond   

Expression  to  evaluate.   

Remarks   

In  debug  builds,  if  the  expression  is  FALSE,  this  macro  displays  a  message  box  with  the  text  of  the  expression,  the  name  of  the  source  file,  and  the  line  number.  The  user  can  ignore  the  assertion,  enter  the  debugger,  or  quit  the  application.   

Example   

ASSERT(rtStartTime  <=  rtEndTime);   


---------------------------------------------------------------   

斷言(ASSERT)的使用,方法非常easy。為什麼要用,剛開始學習的人可能比較迷惑。   
契約式程式設計講的比較清楚,建議能夠先看看這類書。   
一個函式由前置條件、後置條件和不變式組成。在VC中,我們能夠通過斷言來保證這三個條件。能夠大大提高了軟體的質量。   
---------------------------------------------------------------   

假設ASSERT()中的條件不成立(比方  ASSERT(0)  ;    ),會彈出一個比較嚇人的對話方塊。   

點選重試,能夠到達  ASSERT  斷言不成立的那一行,   

此時能夠在watch窗體檢視變數值,找出出錯的原因。   

相關文章