![異常機(jī)制的使用_第1頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/26/f836f91d-c66d-42e0-948c-88a2d6980dc0/f836f91d-c66d-42e0-948c-88a2d6980dc01.gif)
![異常機(jī)制的使用_第2頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/26/f836f91d-c66d-42e0-948c-88a2d6980dc0/f836f91d-c66d-42e0-948c-88a2d6980dc02.gif)
![異常機(jī)制的使用_第3頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/26/f836f91d-c66d-42e0-948c-88a2d6980dc0/f836f91d-c66d-42e0-948c-88a2d6980dc03.gif)
下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、異常機(jī)制的使用 引 言 我們?cè)诰帉戃浖r(shí)不但要追求代碼的正確性,更要關(guān)注程序的容錯(cuò)能力,在環(huán)境不正確或操作不當(dāng)時(shí)不能死機(jī),更不能造成災(zāi)難性后果。程序運(yùn)行時(shí)有些錯(cuò)誤是不可避免的,如內(nèi)存不足、文件打開失敗、數(shù)組下標(biāo)溢出等,這時(shí)要力爭(zhēng)做到排除錯(cuò)誤,繼續(xù)運(yùn)行。 傳統(tǒng)做法是返回一個(gè)錯(cuò)誤代碼,調(diào)用者通過(guò)if等語(yǔ)句測(cè)試返回值來(lái)判斷是否成功。這樣做有幾個(gè)缺點(diǎn):首先,增加的條件語(yǔ)句可能會(huì)帶來(lái)更多的錯(cuò)誤;其次,條件語(yǔ)句是分支點(diǎn),會(huì)增加測(cè)試難度;另外,構(gòu)造函數(shù)沒(méi)有返回值,返回錯(cuò)誤代碼是不可能的。
2、160; C+的異常機(jī)制為我們提供了更好的解決方法。異常處理的基本思想是:當(dāng)出現(xiàn)錯(cuò)誤時(shí)拋出一個(gè)異常,希望它的調(diào)用者能捕獲并處理這個(gè)異常。如果調(diào)用者也不能處理這個(gè)異常,那么異常會(huì)傳遞給上級(jí)調(diào)用,直到被捕獲處理為止。如果程序始終沒(méi)有處理這個(gè)異常,最終它會(huì)被傳到C+運(yùn)行環(huán)境,運(yùn)行環(huán)境捕獲后通常只是簡(jiǎn)單地終止這個(gè)程序。異常機(jī)制使得正常代碼和錯(cuò)誤處理代碼清晰地劃分開來(lái),程序變得非常干凈并且容易維護(hù)。 但是如何合理地使用異常機(jī)制來(lái)達(dá)到預(yù)期的效果呢?MISRA C+給出了一些推薦的規(guī)則,幫助程序員更加合理、可靠地實(shí)現(xiàn)異常機(jī)制。下面將結(jié)合這些規(guī)則對(duì)異
3、常機(jī)制進(jìn)行簡(jiǎn)單的探討。1 在恰當(dāng)?shù)膱?chǎng)合使用恰當(dāng)?shù)奶匦?#160; MISRA C+對(duì)異常的第1條規(guī)則就是: 規(guī)則15-0-1(不容討論):異常機(jī)制只能用來(lái)處理錯(cuò)誤。 異常處理的本質(zhì)是控制流程的轉(zhuǎn)移,但異常機(jī)制是針對(duì)錯(cuò)誤處理的,僅在代碼可能出現(xiàn)異常的情況下使用,不能用來(lái)實(shí)現(xiàn)普通的流程轉(zhuǎn)移。 例如: 語(yǔ)法不會(huì)阻止你這樣做,但殺雞焉用牛刀。這樣不但會(huì)降低程序的可讀性,也會(huì)帶來(lái)更大的開銷。
4、實(shí)際上,用一個(gè)簡(jiǎn)單的if語(yǔ)句就可以實(shí)現(xiàn)上述邏輯。同樣,出于程序流程的清晰性考慮的還有: 規(guī)則15-0-3(強(qiáng)制):不允許通過(guò)goto或者switch語(yǔ)句跳轉(zhuǎn)到try或catch語(yǔ)句塊內(nèi)。2 正確地拋出異常 什么時(shí)候,什么地方,拋出什么樣的異常,都是需要仔細(xì)考慮的。MISRA C+對(duì)此也作了相關(guān)規(guī)定。首先,來(lái)看一下拋出異常對(duì)象的類型中有哪些需要注意的地方。規(guī)則15-0-2(推薦):拋出的異常對(duì)象不應(yīng)該是指針類型。 如果拋出的異常對(duì)象是個(gè)指針類型,指向的是動(dòng)態(tài)創(chuàng)建的對(duì)象,那么這個(gè)對(duì)象應(yīng)該由哪
5、個(gè)函數(shù)來(lái)負(fù)責(zé)銷毀,什么時(shí)候銷毀,都很不清楚。比如說(shuō),如果是在堆中建立的對(duì)象,那通常必須刪除,否則會(huì)造成資源泄漏;如果不是在堆中建立的對(duì)象,通常不能刪除,否則程序的行為將不可預(yù)測(cè)。 規(guī)則15-1-2(強(qiáng)制):不能顯式地把NULL作為異常對(duì)象拋出。 因?yàn)閠hrow(NULL)=tbrow(0),因此NULL會(huì)被當(dāng)作整型捕獲,而不是空指針常量,這可能與程序員的預(yù)期不一致。 通常,很多函數(shù)都是基于function-try-block結(jié)構(gòu)的,即函數(shù)體整個(gè)包含在一個(gè)函數(shù)try塊中。而函數(shù)能拋出什么類
6、型的異常對(duì)象,有以下規(guī)定: 規(guī)則15-5-2(強(qiáng)制):如果一個(gè)函數(shù)聲明時(shí)指定了具體的異常類型,那么它只能拋出指定類型的異常。 規(guī)則15-4-1(強(qiáng)制):如果一個(gè)函數(shù)聲明時(shí)指定了異常的類型,那么在其他編譯單元里該函數(shù)的聲明必須有同樣的指定。 函數(shù)的代碼結(jié)構(gòu)如下:返回值類型函數(shù)名(形參表)throw(類型名表)函數(shù)體 如果函數(shù)在聲明時(shí)沒(méi)有異常規(guī)范,那么它可以拋出任意類型的異常對(duì)象;如果異常類型為空,則表示不拋出任何類型異常。注意這兩者之間的區(qū)別,前者指沒(méi)有
7、throw(類型名表)語(yǔ)句,而后者有throw(類型名表),只是類型名表為空。但如果聲明時(shí)指定了異常的類型,那么它只能拋出指定類型的異常。 另外,函數(shù)原型中的異常聲明要與實(shí)現(xiàn)中的異常聲明一致,否則會(huì)引起異常沖突。由于異常機(jī)制是在運(yùn)行出現(xiàn)異常時(shí)才發(fā)揮作用的,因此如果函數(shù)的實(shí)現(xiàn)中拋出了沒(méi)有在其異常聲明列表中列出的異常,編譯器也許不能檢查出來(lái)。當(dāng)拋出一個(gè)未在其異常聲明列表里的異常類型時(shí),unexpected()函數(shù)會(huì)被調(diào)用,默認(rèn)會(huì)導(dǎo)致std:bad_exception類型的異常被拋出。如果std:bad_exception不在異常聲明列表里,又會(huì)導(dǎo)致termina
8、te()被調(diào)用,從而導(dǎo)致程序結(jié)束。 對(duì)于什么時(shí)候能拋出異常,則有以下規(guī)定: 規(guī)則15-3-1(強(qiáng)制):異常只能在初始化之后而且程序結(jié)束之前拋出。 在執(zhí)行main函數(shù)體之前,是初始化階段,構(gòu)造和初始化靜態(tài)對(duì)象;在main函數(shù)返回后,是終止階段,靜態(tài)對(duì)象被銷毀。在這兩個(gè)階段中如果拋出異常,會(huì)導(dǎo)致程序以不定的方式終止(這依賴于具體的編譯器)。例如: 在這個(gè)例子中,catch塊只能捕獲上面try塊中的異常。如果在對(duì)象c的構(gòu)
9、造函數(shù)或析構(gòu)函數(shù)中拋出異常,并不能被main里的catch塊捕獲,而且會(huì)導(dǎo)致程序終止。 除了上述規(guī)則,還有以下兩個(gè)規(guī)則需要注意: 規(guī)則15-1-1(強(qiáng)制):throw語(yǔ)句中的表達(dá)式本身不能引發(fā)新的異常。 如果在構(gòu)造異常對(duì)象,或者計(jì)算賦值表達(dá)式時(shí)引發(fā)新的異常,那么新的異常會(huì)在本來(lái)要拋出的異常之前被拋出,這與程序員的預(yù)期不一致。 規(guī)則15-1-3(強(qiáng)制):空的throw語(yǔ)句只能出現(xiàn)在catch語(yǔ)句塊中。 空的throw用
10、來(lái)將捕獲的異常再拋出,可以實(shí)現(xiàn)多個(gè)處理程序問(wèn)異常的傳遞。然而,如果在catch語(yǔ)句外用,由于沒(méi)有捕獲到異常,也就沒(méi)有東西可以再拋出,這樣會(huì)導(dǎo)致程序以不定的方式終止(這依賴具體的編譯器)。3 合理地處理異常 由于后面的討論多處涉及到“棧展開”這個(gè)概念,這里先解釋一下。“棧展開”是異常機(jī)制中一個(gè)重要的過(guò)程:在逐層查找用來(lái)處理異常的catch子句時(shí),因?yàn)楫惓6顺鰪?fù)合語(yǔ)句和函數(shù)定義,這個(gè)過(guò)程被稱作“棧展開”。隨著棧的展開,在退出的復(fù)合語(yǔ)句和函數(shù)定義中聲明的局部變量的生命期也結(jié)束,而且這些局部類對(duì)象的析構(gòu)函數(shù)也會(huì)被調(diào)用,這樣能保證內(nèi)存空間得到合理回收。棧展開的概念對(duì)
11、于理解后面的內(nèi)容很重要,我們通過(guò)一個(gè)具體例子進(jìn)一步闡述。 當(dāng)異常發(fā)生時(shí),在函數(shù)調(diào)用鏈中逐層查找該異常的catch子句。在棧展開過(guò)程中函數(shù)foo()首先被檢查到,因?yàn)楫a(chǎn)生異常的語(yǔ)句沒(méi)有被放在try塊中,所以不會(huì)在:foo()中查找針對(duì)該異常的catch子句。棧展開過(guò)程繼續(xù)向上遍歷函數(shù)調(diào)用鏈到達(dá)調(diào)用foo()的函數(shù)。然而在foo()帶著這個(gè)未處理的異常退出之前,棧展開過(guò)程會(huì)銷毀foo()中所有在異常產(chǎn)生之前被創(chuàng)建的局部類對(duì)象。結(jié)果就是:o1、o2的析構(gòu)函數(shù)被調(diào)用,o3已經(jīng)“死亡”,而o4還沒(méi)“出生”。 &
12、#160; 顧名思義,“異常”就是程序運(yùn)行出現(xiàn)了非預(yù)期的情況,或者說(shuō)錯(cuò)誤。因此,出現(xiàn)異常必須有針對(duì)地處理。對(duì)此,MISRA C+首先有如下規(guī)定: 規(guī)則15-3-4(強(qiáng)制):所有可能的流程中顯式拋出來(lái)的異常都應(yīng)該有一個(gè)類型兼容的處理程序。 規(guī)則15-3-2(推薦):至少要有一個(gè)處理程序來(lái)處理所有其他未針對(duì)處理的異常。 如果程序拋出一個(gè)沒(méi)有被處理的異常,程序會(huì)終止,而終止前調(diào)用棧有沒(méi)有被“展開”,動(dòng)態(tài)對(duì)象能不能被析構(gòu),這些都依賴于編譯器。上面兩條規(guī)則規(guī)定了:不但預(yù)期拋出的異常要進(jìn)
13、行處理,其他可能被拋出的異常也要有相應(yīng)的處理措施。請(qǐng)注意規(guī)則15-3-4中“類型兼容”的字眼,C+有非常靈活的類型兼容規(guī)則,尤其對(duì)于類。例如當(dāng)異常對(duì)象是派生類時(shí),“兼容類型”可以是派生類,也可以是基類。后面我們還會(huì)具體討論這個(gè)問(wèn)題。 一個(gè)try塊后可以有多個(gè)catch塊來(lái)捕獲不同的異常。當(dāng)出現(xiàn)異常時(shí),catch處理程序按照其在try塊后出現(xiàn)的順序被逐個(gè)檢查,只要找到一個(gè)匹配的異常類型,后面的異常處理都被忽略。因此,catch處理程序出現(xiàn)的順序很重要。 規(guī)則15-3-6(強(qiáng)制):若一個(gè)try-catch語(yǔ)句塊有多個(gè)處理程序,或者一個(gè)派生類和其部分或全部基類的function-try-block塊有多個(gè)處理程序,處理程序的順序應(yīng)該是先派生類后基類。 規(guī)則15-3-7(強(qiáng)制):
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 咖啡廳裝修合作協(xié)議樣本
- 專賣店裝修分包合同
- 足球場(chǎng)地施工方案
- 建筑工程資金周轉(zhuǎn)居間合同
- 體育場(chǎng)館食堂裝修合同
- 咨詢服務(wù)辦公空間改造協(xié)議
- 工業(yè)園區(qū)改造維修合同
- 家電配送安裝一體化合同
- 鉆樁管線保護(hù)施工方案
- vi版權(quán)轉(zhuǎn)讓合同范例
- 彭大軍橋牌約定卡
- 煙氣管道阻力計(jì)算
- 城鄉(xiāng)環(huán)衛(wèi)一體化保潔服務(wù)迎接重大節(jié)日、活動(dòng)的保障措施
- 醫(yī)院-9S管理共88張課件
- 高考作文復(fù)習(xí):議論文論證方法課件15張
- 2022醫(yī)學(xué)課件前列腺炎指南模板
- MySQL數(shù)據(jù)庫(kù)項(xiàng)目式教程完整版課件全書電子教案教材課件(完整)
- 藥品生產(chǎn)質(zhì)量管理工程完整版課件
- 《網(wǎng)絡(luò)服務(wù)器搭建、配置與管理-Linux(RHEL8、CentOS8)(微課版)(第4版)》全冊(cè)電子教案
- 職業(yè)衛(wèi)生教學(xué)課件生物性有害因素所致職業(yè)性損害
- 降“四高”健康教育課件
評(píng)論
0/150
提交評(píng)論