Windows核心编程 第23章 结束处理程序
第2?3章?結(jié)束處理程序
SEH(結(jié)構(gòu)化異常處理)
????使用?S?E?H的好處就是當(dāng)你編寫(xiě)程序時(shí),只需要關(guān)注程序要完成的任務(wù)。
如果在運(yùn)行時(shí)發(fā)生什么錯(cuò)誤,系統(tǒng)會(huì)發(fā)現(xiàn)并將發(fā)生的問(wèn)題通知你。利用S?E?H,你可以完全不用考慮代碼里是不是有錯(cuò)誤,這樣就把主要的工作同錯(cuò)誤處理分離開(kāi)來(lái)。這樣的分離,可以使你集中精力處理眼前的工作,而將可能發(fā)生的錯(cuò)誤放在后面處理。
????S?E?H實(shí)際包含兩個(gè)主要功能:結(jié)束處理(?termination?handling)和異常處理(?e?x?c?e?p?t?i?o?nh?a?n?d?l?i?n?g)。本章討論結(jié)束處理,下一章討論異常處理。
????注意:不要將結(jié)構(gòu)化異常處理同C?+?+的異常處理相混淆。C?+?+異常處理是一種不同形
式的異常處理,其形式是使用C?+?+關(guān)鍵字c?a?t?c?h和t?h?r?o?w。最后再區(qū)分這兩個(gè)的區(qū)別。
下面是基本調(diào)用樣子:
?
-?-?t?r?y和-?-?f?i?n?a?l?l?y關(guān)鍵字用來(lái)標(biāo)出結(jié)束處理程序兩段代碼的輪廓。在上面的代碼段中,操作系統(tǒng)和編譯程序共同來(lái)確保結(jié)束處理程序中的?-?-?f?i?n?a?l?l?y代碼塊能夠被執(zhí)行,不管保護(hù)體(?t?r?y塊)是如何退出的。不論你在保護(hù)體中使用?r?e?t?u?r?n,還是g?o?t?o,或者是l?o?n?g?j?u?m?p,結(jié)束處理程序(f?i?n?a?l?l?y塊)都將被調(diào)用。
要完成這些事情,編譯程序必須生成附加的代碼,系統(tǒng)要執(zhí)行額外的工作。在不同的C?P?U上,結(jié)束處理所需要的步驟也不同。例如,在?A?l?p?h?a處理器上,必須執(zhí)行幾百個(gè)甚至幾千個(gè)C?P?U指令來(lái)捕捉t?r?y塊中的過(guò)早返回并調(diào)用f?i?n?a?l?l?y塊。在編寫(xiě)代碼時(shí),就應(yīng)該避免引起結(jié)束處理程序的t?r?y塊中的過(guò)早退出,因?yàn)槌绦虻男阅軙?huì)受到影響。
注意當(dāng)控制流自然地離開(kāi)t?r?y塊并進(jìn)入f?i?n?a?l?l?y塊(就像在F?u?n?c?e?n?s?t?e?i?n?1中)時(shí),進(jìn)入f?i?n?a?l?l?y塊的系統(tǒng)開(kāi)銷是最小的。在x86?CPU上使用微軟的編譯程序,當(dāng)執(zhí)行離開(kāi)?try?塊進(jìn)入f?i?n?a?l?l?y塊時(shí),只有一個(gè)機(jī)器指令被執(zhí)行。
常用舉例:
1.
會(huì)彈出崩潰框,但是點(diǎn)擊關(guān)閉后會(huì)執(zhí)行finally代碼,但是不會(huì)執(zhí)行第二個(gè)messagebox:
2.下面這個(gè)函數(shù)返回14,自己好好理解下:
3.下面這個(gè),按照書(shū)上的意思是返回2,然而是沒(méi)編譯過(guò)去(vs2012?C++)
?
4.書(shū)上寫(xiě)了三個(gè)函數(shù),同功能,直接截圖過(guò)來(lái)了
(1)
(2)
(3)
5.最終的邊界
? ? 為了幫助避免在t?r?y塊中使用r?e?t?u?r?n語(yǔ)句,微軟在其C?/?C?+?+編譯程序中增加了另一個(gè)關(guān)鍵字-?-l?e?a?v?e。這里是F?u?n?c?a?r?m?a?4版,它使用了-?-?l?e?a?v?e關(guān)鍵字:
?如果直接這樣:
那么return導(dǎo)致的進(jìn)入finally的狀態(tài)不是流入的,也就是需要很多輔助代碼來(lái)處理,如果直接使用__leave
那就是類似如下優(yōu)化:
從而優(yōu)化了執(zhí)行時(shí)間。
關(guān)于f?i?n?a?l?l?y塊的說(shuō)明
已經(jīng)明確區(qū)分了強(qiáng)制執(zhí)行f?i?n?a?l?l?y塊的兩種情況:
??從t?r?y塊進(jìn)入f?i?n?a?l?l?y塊的正常控制流。
??局部展開(kāi):從t?r?y塊的過(guò)早退出(g?o?t?o、l?o?n?g?j?u?m?p、c?o?n?t?i?n?u?e、b?r?e?a?k、r?e?t?u?r?n等)強(qiáng)制控制轉(zhuǎn)移到f?i?n?a?l?l?y塊。
????第三種情況,全局展開(kāi)(?global?unwind),在發(fā)生的時(shí)候沒(méi)有明顯的標(biāo)識(shí),我們?cè)诒菊虑懊?/span>F?u?n?c?f?u?r?t?e?r?1函數(shù)中已經(jīng)見(jiàn)到。在F?u?n?c?f?u?r?t?e?r?1的t?r?y塊中,有一個(gè)對(duì)F?u?n?c?i?n?a?t?o?r函數(shù)的調(diào)用。如果F?u?n?c?i?n?a?t?o?r函數(shù)引起一個(gè)內(nèi)存訪問(wèn)違規(guī)(?memory?access?violation),一個(gè)全局展開(kāi)會(huì)使F?u?n?c?f?u?r?t?e?r?1的f?i?n?a?l?l?y塊執(zhí)行。下一章將詳細(xì)討論全局展開(kāi)。
由于以上三種情況中某一種的結(jié)果而導(dǎo)致f?i?n?a?l?l?y塊中的代碼開(kāi)始執(zhí)行。為了確定是哪一種情況引起f?i?n?a?l?l?y塊執(zhí)行,可以調(diào)用內(nèi)部函數(shù)(或內(nèi)蘊(yùn)函數(shù),intrinsic?function)Abnormal?Te?r?m?i?n?a?t?i?o?n:
BOOL?AbnormalTermination();
這個(gè)內(nèi)部函數(shù)只在f?i?n?a?l?l?y塊中調(diào)用,返回一個(gè)B?o?o?l?e?a?n值。指出與f?i?n?a?l?l?y塊相結(jié)合的t?r?y塊是否過(guò)早退出。換句話說(shuō),如果控制流離開(kāi)?t?r?y塊并自然進(jìn)入f?i?n?a?l?l?y塊,A?b?n?o?r?m?a?l?Te?r?m?i?n?a?t?i?o?n將返回FA?L?S?E。如果控制流非正常退出?t?r?y塊?—?通常由于g?o?t?o、r?e?t?u?r?n、b?r?e?a?k或c?o?n?t?i?n?u?e語(yǔ)句引起的局部展開(kāi),或由于內(nèi)存訪問(wèn)違規(guī)或其他異常引起的全局展開(kāi)?—?對(duì)A?b?n?o?r?m?a?l?Te?r?m?i?n?a?t?i?o?n的調(diào)用將返回T?R?U?E。沒(méi)有辦法區(qū)別f?i?n?a?l?l?y塊的執(zhí)行是由于全局展開(kāi)還是由于局部展開(kāi)。但這通常不會(huì)成為問(wèn)題,因?yàn)榭梢员苊饩帉?xiě)執(zhí)行局部展開(kāi)的代碼。
使用結(jié)束處理程序的理由:
??簡(jiǎn)化錯(cuò)誤處理,因所有的清理工作都在一個(gè)位置并且保證被執(zhí)行。
??提高程序的可讀性。
??使代碼更容易維護(hù)。
??如果使用得當(dāng),具有最小的系統(tǒng)開(kāi)銷。
Try和__Try區(qū)別:
異常處理
?
結(jié)果是輸出兩個(gè)對(duì)話框,沒(méi)有崩潰界面。
SEH
結(jié)果是先輸出一個(gè)崩潰頁(yè)面,點(diǎn)擊關(guān)閉,彈出matk1對(duì)話框。
?
?
總結(jié)
以上是生活随笔為你收集整理的Windows核心编程 第23章 结束处理程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows PE第6章 栈与重定位表
- 下一篇: Windows核心编程 第2 4章 异常