剖析ASSERT函数
2019獨角獸企業重金招聘Python工程師標準>>>
搜集與總結了assert函數的用法,記于此,以備后續與查找使用: ****身在Windows的世界,但還是深愛著我的它---Linux****I love Linux forever***** ****先給一個小例子,熱熱身*********Never give up **************請看下面的程序清單badptr.c:
#include
#include
#include
int main( void )
{
FILE *fp;
fp = fopen( "test.txt", "w" );//以可寫的方式打開一個文件,如果不存在就創建一個同名文件
assert( fp ); //所以這里不會出錯
fclose( fp );
fp = fopen( "noexitfile.txt", "r" );//以只讀的方式打開一個文件,如果不存在就打開文件失敗
assert( fp ); //所以這里出錯
fclose( fp ); //程序永遠都執行不到這里來
return 0;
}
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp' failed.
已放棄
使用assert的缺點是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。
在調試結束后,可以通過在包含#include的語句之前插入 #define NDEBUG 來禁用assert調用,示例代碼如下:
#include
#define NDEBUG
#include
用法總結與注意事項:
1)在函數開始處檢驗傳入參數的合法性
如:
int resetBufferSize(int nNewSize)
{
//功能:改變緩沖區大小,
//參數:nNewSize 緩沖區新長度
//返回值:緩沖區當前長度
//說明:保持原信息內容不變 nNewSize<=0表示清除緩沖區
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
2)每個assert只檢驗一個條件,因為同時檢驗多個條件時,如果斷言失敗,無法直觀的判斷是哪個條件失敗
不好: assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好: assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
3)不能使用改變環境的語句,因為assert只在DEBUG個生效,如果這么做,會使用程序在真正運行時遇到問題
錯誤: assert(i++ < 100)
這是因為如果出錯,比如在執行之前i=100,那么這條語句就不會執行,那么i++這條命令就沒有執行。
正確: assert(i < 100)
i++;
4)assert和后面的語句應空一行,以形成邏輯和視覺上的一致感
5)有的地方,assert不能代替條件過濾。
? 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 <= 100; ++i) assert (do_something () == 0);然后,你可能會發現這樣會使得性能大大降低,從而在創新編譯使使用NDEGUG參數。這將移除整個assert宏,這就將do_something( )也被移除了,再也不被調用。為了糾正錯誤,你應該這樣寫:
for (i = 0; i <= 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);,這將幫助你檢測函數的錯誤使用,這也給源代碼閱讀者很清晰的印象,那就是在這里對函數的參數值有限制。
說了這么多,行動起來吧,大膽的在你的程序中使用斷言。
http://www.programfan.com/blog/article.asp?id=10284
--------------------------------------------------------------- ??
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)的使用,方法很簡單。為什么要用,初學者可能比較迷惑。 ??
契約式編程講的比較清楚,建議可以先看看這類書。 ??
一個函數由前置條件、后置條件和不變式組成。在VC中,我們可以通過斷言來保證這三個條件。可以大大提高了軟件的質量。 ??
--------------------------------------------------------------- ??
如果ASSERT()中的條件不成立(比如 ?ASSERT(0) ?; ???),會彈出一個比較嚇人的對話框。 ??
點擊重試,可以到達 ?ASSERT ?斷言不成立的那一行, ??
此時可以在watch窗口查看變量值,找出出錯的原因。 ??
轉載于:https://my.oschina.net/u/2344808/blog/397925
總結
以上是生活随笔為你收集整理的剖析ASSERT函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到小孩被水淹是什么意思
- 下一篇: mac os x10.8下如何使用git