www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式客棧
[導(dǎo)讀][導(dǎo)讀]大家好,我是逸珺。今天來分享整理如何正確的使用斷言。何為斷言斷言一般是用于檢測(cè)在某個(gè)程序位置程序必須滿足某些條件的宏。一般用的多的可以分兩種種情況:前置條件:在某個(gè)程度點(diǎn)開始的地方后置條件:在某段程序執(zhí)行結(jié)束后,一般用于檢測(cè)執(zhí)行結(jié)果斷言發(fā)生表示程序中存在錯(cuò)誤。因此,斷言是...

[導(dǎo)讀] 大家好,我是逸珺。

今天來分享整理如何正確的使用斷言。

何為斷言

斷言一般是用于檢測(cè)在某個(gè)程序位置程序必須滿足某些條件的宏。一般用的多的可以分兩種種情況:

  • 前置條件:在某個(gè)程度點(diǎn)開始的地方

  • 后置條件:在某段程序執(zhí)行結(jié)束后,一般用于檢測(cè)執(zhí)行結(jié)果

斷言發(fā)生表示程序中存在錯(cuò)誤。因此,斷言是提高程序可靠性的有效手段。也是開發(fā)階段快速定位問題的一種很好防御式編程方法。

在C語言中,斷言是一些條件判斷的宏。比如C語言內(nèi)置斷言是用標(biāo)準(zhǔn)的 assert 宏實(shí)現(xiàn)的。當(dāng)宏執(zhí)行時(shí),assert 的參數(shù)必須為真,否則程序中止并打印錯(cuò)誤消息。

比如,在IAR中:

#define?assert(test)?((test)???(void)?0?:?abort())
也可以編程者自己定義,比如:

#define?assert(arg)?{?if(?!(arg)?)?{?printf("assert?in?File="__FILE__"?Line=%d?",__LINE__);?return;?}?}

該怎么用

前置條件

比如某一個(gè)函數(shù)代碼:

#define?ALLOWED_SIZE??(1024)
int?func(int?size,?char?*buffer?)?
{
??assert(?size?<=?ALLOWED_SIZE?);
??assert(?format?!=?NULL?);
??...
}
這個(gè)函數(shù)里,使用了兩次斷言判斷函數(shù)執(zhí)行的前置條件:

  • size必須要不大于ALLOWED_SIZE,func函數(shù)才真正執(zhí)行其任務(wù)。因此,如果輸入的size超過1024,func不會(huì)做任何處理。
  • buffer傳入的地址必須不是NULL,否則func函數(shù)不會(huì)執(zhí)行。
具體斷言判斷失敗了,斷言宏干了什么,需要看看這個(gè)宏的實(shí)現(xiàn),有可能是直接返回,有可能整個(gè)程序直接終止執(zhí)行。所以看看其實(shí)現(xiàn)就知道了。

后置條件

后置條件斷言一般是指判斷函數(shù)的執(zhí)行結(jié)果。比如:

int?func(int?size,?char?*buffer?)?
{
?int?result;
?
?/*中間處理部分更新這個(gè)返回值*/
??...
??
??assert(?result?<=?ALLOWED_SIZE?);
??return?result;
}
這樣寫表示這個(gè)函數(shù)的返回值永遠(yuǎn)不會(huì)大于ALLOWED_SIZE。如果大于了,就證明產(chǎn)生錯(cuò)誤了。

什么時(shí)候用

斷言的最常用和最有效的用途是檢查前置條件——即指定和檢查函數(shù)的輸入條件。兩個(gè)非常常見的用途:

  • 指針不是 NULL。
  • 索引和邊界范圍值是在設(shè)計(jì)的合理范圍之類。
尤其如果寫一個(gè)代碼包給其他的人調(diào)用的時(shí)候,這樣處理會(huì)使代碼提高健壯性,易用性。

當(dāng)代碼調(diào)用帶有前置條件的斷言時(shí),必須要確保滿足該函數(shù)的前置條件。但這并不意味著必須斷言檢查調(diào)用的每個(gè)函數(shù)的參數(shù)!

調(diào)試的便利

  • 如果在程序測(cè)試和調(diào)試期間違反了前置條件,也就是說斷言異常了,則調(diào)用包含前置條件的函數(shù)的代碼中存在bug。

  • 如果在程序測(cè)試和調(diào)試期間違反了后置條件,則該斷言前面部分代碼可能有bug。

這樣利用斷言的打印,或者檢測(cè)到斷言指定的行為,就可以很快速的發(fā)現(xiàn)bug,而避免要在后期反復(fù)測(cè)試才能識(shí)別出bug。

那么什么時(shí)候用?首先,區(qū)分程序錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤很重要:

  • 程序錯(cuò)誤是一個(gè)bug,永遠(yuǎn)不應(yīng)該發(fā)生。
  • 運(yùn)行時(shí)錯(cuò)誤可能在程序執(zhí)行期間的任何時(shí)間發(fā)生。
斷言不是處理運(yùn)行時(shí)錯(cuò)誤的機(jī)制。例如,由于用戶在預(yù)期為正數(shù)時(shí)無意中輸入了負(fù)數(shù)而導(dǎo)致的斷言異常就是程序設(shè)計(jì)不合理。像這樣的情況必須通過適當(dāng)?shù)腻e(cuò)誤檢查和恢復(fù)代碼(比如彈出一個(gè)提示輸入合理范圍)來處理,而不是通過斷言來處置。

當(dāng)然,實(shí)際是程序都可能會(huì)有bug,這些bug會(huì)在運(yùn)行時(shí)出現(xiàn)。確切地說,斷言要檢查什么條件以及運(yùn)行時(shí)錯(cuò)誤檢查代碼要檢查什么是設(shè)計(jì)問題。

如前所說,斷言在可重用庫中非常有效。比如在QT中:

int?main(int?argc,?char?*argv[])
{
????QVector?<int>?list;
????list.append(0);
????list.append(1);
????qDebug()?<list.at(2);
????
????return?0;
}
一運(yùn)行,就會(huì)有這樣的結(jié)果:

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
因?yàn)閘ist只有兩個(gè)元素,list.at(2)則是去訪問第3個(gè),顯然訪問的元素不存在,所以就斷言了。

—— The End?—


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉