天天看點

Windows核心程式設計 第23章 結束處理程式

第2 3章 結束處理程式

SEH(結構化異常處理)

S E H的好處就是當你編寫程式時,隻需要關注程式要完成的任務。

如果在運作時發生什麼錯誤,系統會發現并将發生的問題通知你。利用S E H,你可以完全不用考慮代碼裡是不是有錯誤,這樣就把主要的工作同錯誤處理分離開來。這樣的分離,可以使你集中精力處理眼前的工作,而将可能發生的錯誤放在後面處理。

實際包含兩個主要功能:結束處理( termination handling)和異常處理( e x c e p t i o nh a n d l i n g)。本章讨論結束處理,下一章讨論異常處理。

:不要将結構化異常處理同C + +的異常處理相混淆。C + +異常處理是一種不同形

式的異常處理,其形式是使用C + +關鍵字c a t c h和t h r o w。最後再區分這兩個的差別。

下面是基本調用樣子:

Windows核心程式設計 第23章 結束處理程式

- - t r y和- - f i n a l l y關鍵字用來标出結束處理程式兩段代碼的輪廓。在上面的代碼段中,作業系統和編譯程式共同來確定結束處理程式中的 - - f i n a l l y代碼塊能夠被執行,不管保護體( t r y塊)是如何退出的。不論你在保護體中使用

要完成這些事情,編譯程式必須生成附加的代碼,系統要執行額外的工作。在不同的C P U上,結束處理所需要的步驟也不同。例如,在 A l p h a處理器上,必須執行幾百個甚至幾千個C P U指令來捕捉t r y塊中的過早傳回并調用f i n a l l y塊。在編寫代碼時,就應該避免引起結束處理程式的t r y塊中的過早退出,因為程式的性能會受到影響。

注意當控制流自然地離開t r y塊并進入f i n a l l y塊(就像在F u n c e n s t e i n 1中)時,進入f i n a l l y塊的系統開銷是最小的。在x86 CPU上使用微軟的編譯程式,當執行離開 try 塊進入f i n a l l y塊時,隻有一個機器指令被執行。

常用舉例:

1.

Windows核心程式設計 第23章 結束處理程式

會彈出崩潰框,但是點選關閉後會執行finally代碼,但是不會執行第二個messagebox:

Windows核心程式設計 第23章 結束處理程式
Windows核心程式設計 第23章 結束處理程式

2.下面這個函數傳回14,自己好好了解下:

Windows核心程式設計 第23章 結束處理程式

3.下面這個,按照書上的意思是傳回2,然而是沒編譯過去(vs2012 C++)

Windows核心程式設計 第23章 結束處理程式

4.書上寫了三個函數,同功能,直接截圖過來了

(1)

Windows核心程式設計 第23章 結束處理程式

(2)

Windows核心程式設計 第23章 結束處理程式

(3)

Windows核心程式設計 第23章 結束處理程式

5.最終的邊界

t r y塊中使用r e t u r n語句,微軟在其C / C + +編譯程式中增加了另一個關鍵字- -l e a v e。這裡是F u n c a r m a 4版,它使用了- - l e a v e關鍵字:

 如果直接這樣:

那麼return導緻的進入finally的狀态不是流入的,也就是需要很多輔助代碼來處理,如果直接使用__leave

Windows核心程式設計 第23章 結束處理程式

那就是類似如下優化:

Windows核心程式設計 第23章 結束處理程式

進而優化了執行時間。

關于f i n a l l y塊的說明

已經明确區分了強制執行f i n a l l y塊的兩種情況:

• 從t r y塊進入f i n a l l y塊的正常控制流。

• 局部展開:從t r y塊的過早退出(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等)強制控制轉移到f i n a l l y塊。

global unwind),在發生的時候沒有明顯的辨別,我們在本章前面F u n c f u r t e r 1函數中已經見到。在F u n c f u r t e r 1的t r y塊中,有一個對F u n c i n a t o r函數的調用。如果F u n c i n a t o r函數引起一個記憶體通路違規( memory access violation),一個全局展開會使F u n c f u r t e r 1的f i n a l l y塊執行。下一章将詳細讨論全局展開。

由于以上三種情況中某一種的結果而導緻f i n a l l y塊中的代碼開始執行。為了确定是哪一種情況引起f i n a l l y塊執行,可以調用内部函數(或内蘊函數,intrinsic function)Abnormal Te r m i n a t i o n:

BOOL AbnormalTermination();

這個内部函數隻在f i n a l l y塊中調用,傳回一個B o o l e a n值。指出與f i n a l l y塊相結合的t r y塊是否過早退出。換句話說,如果控制流離開 t r y塊并自然進入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語句引起的局部展開,或由于記憶體通路違規或其他異常引起的全局展開 — 對A b n o r m a l Te r m i n a t i o n的調用将傳回T R U E。沒有辦法差別f i n a l l y塊的執行是由于全局展開還是由于局部展開。但這通常不會成為問題,因為可以避免編寫執行局部展開的代碼。

使用結束處理程式的理由:

• 簡化錯誤處理,因所有的清理工作都在一個位置并且保證被執行。

• 提高程式的可讀性。

• 使代碼更容易維護。

• 如果使用得當,具有最小的系統開銷。

Try和__Try差別:

異常處理

Windows核心程式設計 第23章 結束處理程式

結果是輸出兩個對話框,沒有崩潰界面。

Windows核心程式設計 第23章 結束處理程式

SEH

Windows核心程式設計 第23章 結束處理程式

結果是先輸出一個崩潰頁面,點選關閉,彈出matk1對話框。

Windows核心程式設計 第23章 結束處理程式
Windows核心程式設計 第23章 結束處理程式

繼續閱讀