何為斷言
斷言一般是用于檢測在某個程序位置程序必須滿足某些條件的宏。一般用的多的可以分兩種種情況:
-
前置條件:在某個程度點開始的地方
-
后置條件:在某段程序執(zhí)行結束后,一般用于檢測執(zhí)行結果
斷言發(fā)生表示程序中存在錯誤。因此,斷言是提高程序可靠性的有效手段。也是開發(fā)階段快速定位問題的一種很好防御式編程方法。
在C語言中,斷言是一些條件判斷的宏。比如C語言內(nèi)置斷言是用標準的 assert 宏實現(xiàn)的。當宏執(zhí)行時,assert 的參數(shù)必須為真,否則程序中止并打印錯誤消息。
比如,在IAR中:
#define assert(test) ((test) ? (void) 0 : abort())
也可以編程者自己定義,比如:
#define assert(arg) { if( !(arg) ) { printf("assert in File="__FILE__" Line=%d ",__LINE__); return; } }
該怎么用
前置條件
比如某一個函數(shù)代碼:
#define ALLOWED_SIZE (1024)
int func(int size, char *buffer )
{
assert( size <= ALLOWED_SIZE );
assert( format !=
NULL );
...
}
這個函數(shù)里,使用了兩次斷言判斷函數(shù)執(zhí)行的前置條件:
-
size必須要不大于ALLOWED_SIZE,func函數(shù)才真正執(zhí)行其任務。因此,如果輸入的size超過1024,func不會做任何處理。
-
buffer傳入的地址必須不是NULL,否則func函數(shù)不會執(zhí)行。
具體斷言判斷失敗了,斷言宏干了什么,需要看看這個宏的實現(xiàn),有可能是直接返回,有可能整個程序直接終止執(zhí)行。所以看看其實現(xiàn)就知道了。
后置條件
后置條件斷言一般是指判斷函數(shù)的執(zhí)行結果。比如:
int func(int size, char *buffer )
{
int result;
/*中間處理部分更新這個返回值*/
...
assert( result <= ALLOWED_SIZE );
return result;
}
這樣寫表示這個函數(shù)的返回值永遠不會大于ALLOWED_SIZE。如果大于了,就證明產(chǎn)生錯誤了。
什么時候用
斷言的最常用和最有效的用途是檢查前置條件——即指定和檢查函數(shù)的輸入條件。兩個非常常見的用途:
-
指針不是 NULL。
-
索引和邊界范圍值是在設計的合理范圍之類。
尤其如果寫一個代碼包給其他的人調(diào)用的時候,這樣處理會使代碼提高健壯性,易用性。
當代碼調(diào)用帶有前置條件的斷言時,必須要確保滿足該函數(shù)的前置條件。但這并不意味著必須斷言檢查調(diào)用的每個函數(shù)的參數(shù)!
調(diào)試的便利:
-
如果在程序測試和調(diào)試期間違反了前置條件,也就是說斷言異常了,則調(diào)用包含前置條件的函數(shù)的代碼中存在bug。
-
如果在程序測試和調(diào)試期間違反了后置條件,則該斷言前面部分代碼可能有bug。
這樣利用斷言的打印,或者檢測到斷言指定的行為,就可以很快速的發(fā)現(xiàn)bug,而避免要在后期反復測試才能識別出bug。
那么什么時候用?首先,區(qū)分程序錯誤和運行時錯誤很重要:
-
程序錯誤是一個bug,永遠不應該發(fā)生。
-
運行時錯誤可能在程序執(zhí)行期間的任何時間發(fā)生。
斷言不是處理運行時錯誤的機制。例如,由于用戶在預期為正數(shù)時無意中輸入了負數(shù)而導致的斷言異常就是程序設計不合理。像這樣的情況必須通過適當?shù)腻e誤檢查和恢復代碼(比如彈出一個提示輸入合理范圍)來處理,而不是通過斷言來處置。
當然,實際是程序都可能會有bug,這些bug會在運行時出現(xiàn)。確切地說,斷言要檢查什么條件以及運行時錯誤檢查代碼要檢查什么是設計問題。
如前所說,斷言在可重用庫中非常有效。比如在QT中:
int main(int argc, char *argv[])
{
QVector <
int>
list;
list.append(
0);
list.append(
1);
qDebug() <<
list.at(
2);
return 0;
}
一運行,就會有這樣的結果:
ASSERT failure in QVector::at:
"index out of range", file C:\Qt\Qt5
.7.1\
5.7\mingw53_32\include/QtCore/qvector.h, line
429
assert in File=..\src\main.cpp Line=
4
因為list只有兩個元素,list.at(2)則是去訪問第3個,顯然訪問的元素不存在,所以就斷言了。
往期推薦:
一份硬核的QT開發(fā)經(jīng)驗及資料分享,長文收藏!
分享嵌入式內(nèi)存管理的一些知識
分享一個簡潔易用的嵌入式操作系統(tǒng)內(nèi)核
本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。