C語(yǔ)言斷言assert的用法_第1頁(yè)
C語(yǔ)言斷言assert的用法_第2頁(yè)
C語(yǔ)言斷言assert的用法_第3頁(yè)
免費(fèi)預(yù)覽已結(jié)束,剩余1頁(yè)可下載查看

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、assert 的用法assert(<expression>);當(dāng)expression結(jié)果為 假”時(shí),會(huì)在stderr中輸出這條語(yǔ)句所在的文件名和行 號(hào),以及這條表達(dá)式。這只在調(diào)試版本中起作用,在 Release版本中不會(huì)產(chǎn)生任 何代碼。通常當(dāng)我們使用assert時(shí),都在強(qiáng)烈說(shuō)明一個(gè)含義:在這里必然如此。它 通常用于一個(gè)函數(shù)的先驗(yàn)條件和后驗(yàn)條件的檢查。比如我寫一個(gè)C風(fēng)格復(fù)制字符串的函數(shù),并且認(rèn)為調(diào)用者不應(yīng)該傳入NULL指針:char*clone_string(constchar*source)char*result;assert(source!=NULL);result=(char*

2、)malloc(strlen(source)+1);if(result!=NULL)strcpy(result,source);assert(strcmp(result,source)=0);returnresult;注意到我對(duì)source是否為NULL是用assert檢查的,但對(duì)result是不是為 NULL是用if語(yǔ)句判斷的,這是因?yàn)樵谡{(diào)用代碼正確的情況下source必然不為NULL,如果斷言失敗,說(shuō)明調(diào)用代碼中有錯(cuò)誤,需要修改;但 result作為 malloc的返回值則不一定,在 malloc代碼無(wú)誤的情況下仍然可能返回NUL 當(dāng)內(nèi)存塊不足時(shí)。最后又用assert對(duì)strcpy的結(jié)果進(jìn)

3、行檢查,因?yàn)橹灰a正 確,無(wú)論什么情況 strcpy 應(yīng)該正常完成復(fù)制,它沒有 malloc 那種異常情況存 在。在編程精粹第二章(自己設(shè)計(jì)并使用斷言)開始的一段話把a(bǔ)ssert的用途說(shuō)的很清楚:利用編譯程序自動(dòng)查錯(cuò)固然好,但我敢說(shuō)只要你觀察一下項(xiàng) 目中那些比較明顯的錯(cuò)誤,就會(huì)發(fā)現(xiàn)編譯程序所查出的只是其中的一小部分。 我還敢說(shuō),如果排除掉了程序中的所有錯(cuò)誤那么在大部分時(shí)間內(nèi)程序都會(huì)正確 工作。還記得第 1 章中的下面代碼嗎?strCopy=memcpy(malloc(length),str,length);該語(yǔ)句在多數(shù)情況下都會(huì)工作得很好,除非malloc的調(diào)用產(chǎn)生失敗。當(dāng)malloc失敗時(shí)

4、,就會(huì)給 memcpy返回一個(gè)NULL指針。由于memcpy處理不了 NULL指針,所以出現(xiàn)了錯(cuò)誤。如果你很走運(yùn),在交付之前這個(gè)錯(cuò)誤導(dǎo)致程序的 癱瘓,從而暴露出來(lái)。但是如果你不走運(yùn),沒有及時(shí)地發(fā)現(xiàn)這個(gè)錯(cuò)誤,那某位 顧客就一定會(huì) “走運(yùn)”了。編譯程序查不出這種或其他類似的錯(cuò)誤。同樣,編譯 程序也查不出算法的錯(cuò)誤,無(wú)法驗(yàn)證程序員所作的假定。或者更一般地,編譯 程序也查不出所傳遞的參數(shù)是否有效。尋找這種錯(cuò)誤非常艱苦,只有技術(shù)非常高的程序員或者測(cè)試者才能將它們 根除并且不會(huì)引起其他的問題。然而假如你知道應(yīng)該怎樣去做的話,自動(dòng)尋找這種錯(cuò)誤就變得很容易了。兩個(gè)版本的故事讓我們直接進(jìn)入memcpy,看看怎樣

5、才能查出上面的錯(cuò)誤。最初的解決辦法 是使memcpy對(duì)NULL指針進(jìn)行檢查,如果指針為 NULL,就給出一條錯(cuò)誤信 息,并中止 memcpy 的執(zhí)行。下面是這種解法對(duì)應(yīng)的程序。voidmemcpy(void*pvTo,void*pvFrom,size_tsize)void*pbTo=(byte*)pvTo;void*pbFrom=(byte*)pvFrom;if(pvTo=NULL|pvFrom=NULL)fprintf(stderr,“ Badargsinmne”m)c;pyabort();while(size->0)*pbTo+=*pbFrom+;return(pvTo);只要調(diào)用時(shí)

6、錯(cuò)用了 NULL指針,這個(gè)函數(shù)就會(huì)查出來(lái)。所存在的唯一問題是 其中的測(cè)試代碼使整個(gè)函數(shù)的大小增加了一倍,并且降低了該函數(shù)的執(zhí)行速 度。如果說(shuō)這是 “越治病越糟 ”,確實(shí)有理,因?yàn)樗稽c(diǎn)不實(shí)用。要解決這個(gè)問 題需要利用C的預(yù)處理程序。如果保存兩個(gè)版本怎么樣?一個(gè)整潔快速用于程序的交付;另一個(gè)臃腫緩 慢件(因?yàn)榘祟~外的檢查),用于調(diào)試。這樣就得同時(shí)維護(hù)同一程序的兩 個(gè)版本,并利用C的預(yù)處理程序有條件地包含或不包含相應(yīng)的檢查部分。voidmemcpy(void*pvTo,void*pvFrom,size_tsize)void*pbTo=(byte*)pvTo;void*pbFrom=(byte*

7、)pvFrom;#ifdefDEBUGif(pvTo=NULL|pvFrom=NULL)fprintf(stderr,“ Badargsinmne”m)c;pyabort();#endifwhile(size->0)*pbTo+=*pbFrom+;return(pvTo);這種想法是同時(shí)維護(hù)調(diào)試和非調(diào)試(即交付)兩個(gè)版本。在程序的編寫過(guò) 程中,編譯其調(diào)試版本,利用它提供的測(cè)試部分在增加程序功能時(shí)自動(dòng)地查 錯(cuò)。在程序編完之后,編譯其交付版本,封裝之后交給經(jīng)銷商。當(dāng)然,你不會(huì)傻到直到交付的最后一刻才想到要運(yùn)行打算交付的程序,但 在整個(gè)的開發(fā)工程中,都應(yīng)該使用程序的調(diào)試版本。正如在這一章和下一

8、章所 建,這樣要求的主要原因是它可以顯著地減少程序的開發(fā)時(shí)間。讀者可以設(shè)想 一下:如果程序中的每個(gè)函數(shù)都進(jìn)行一些最低限度的錯(cuò)誤檢查,并對(duì)一些絕不 應(yīng)該出現(xiàn)的條件進(jìn)行測(cè)試的活,相應(yīng)的應(yīng)用程序會(huì)有多么健壯。這種方法的關(guān)鍵是要保證調(diào)試代碼不在最終產(chǎn)品中出現(xiàn)。利用斷言進(jìn)行補(bǔ)救說(shuō)老實(shí)話 memcpy 中的調(diào)試碼編得非常蹩腳,且頗有點(diǎn)喧賓奪主的意味。 因此盡管它能產(chǎn)生很好的結(jié)果,多數(shù)程序員也不會(huì)容忍它的存在,這就是聰明 的程序員決定將所有的調(diào)試代碼隱藏在斷言 assert 中的緣故。 assert 是個(gè)宏,它 定義在頭文件assert.h中。assert雖然不過(guò)是對(duì)前面所見# ifdef部分代碼的替 換,

9、但利用這個(gè)宏,原來(lái)的代碼從 7 行變成了 1 行。voidmemcpy(void*pvTo,void*pvFrom,size_tsize)void*pbTo=(byte*)pvTo;void*pbFrom=(byte*)pvFrom;assert(pvTo!=NULL&&pvFrom!=NULL);while(size->0)*pbTo+=*pbFrom+;return(pvTo);aasert是個(gè)只有定義了 DEBUG才起作用的宏,如果其參數(shù)的計(jì)算結(jié)果為 假,就中止調(diào)用程序的執(zhí)行。因此在上面的程序中任何一個(gè)指針為NULL都會(huì)引發(fā) assert。assert并不是一個(gè)倉(cāng)促拼湊起來(lái)的宏,為了不在程序的交付版本和調(diào)試版本 之間引起重要的差別,需要對(duì)其進(jìn)行仔細(xì)的定義。宏assert不應(yīng)該弄亂內(nèi)存,不應(yīng)該對(duì)未初始化的數(shù)據(jù)進(jìn)行初始化,即

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論