Windows核心编程 第23章 结束处理程序
第2?3章?結束處理程序
SEH(結構化異常處理)
????使用?S?E?H的好處就是當你編寫程序時,只需要關注程序要完成的任務。
如果在運行時發生什么錯誤,系統會發現并將發生的問題通知你。利用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。最后再區分這兩個的區別。
下面是基本調用樣子:
?
-?-?t?r?y和-?-?f?i?n?a?l?l?y關鍵字用來標出結束處理程序兩段代碼的輪廓。在上面的代碼段中,操作系統和編譯程序共同來確保結束處理程序中的?-?-?f?i?n?a?l?l?y代碼塊能夠被執行,不管保護體(?t?r?y塊)是如何退出的。不論你在保護體中使用?r?e?t?u?r?n,還是g?o?t?o,或者是l?o?n?g?j?u?m?p,結束處理程序(f?i?n?a?l?l?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.
會彈出崩潰框,但是點擊關閉后會執行finally代碼,但是不會執行第二個messagebox:
2.下面這個函數返回14,自己好好理解下:
3.下面這個,按照書上的意思是返回2,然而是沒編譯過去(vs2012?C++)
?
4.書上寫了三個函數,同功能,直接截圖過來了
(1)
(2)
(3)
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
那就是類似如下優化:
從而優化了執行時間。
關于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區別:
異常處理
?
結果是輸出兩個對話框,沒有崩潰界面。
SEH
結果是先輸出一個崩潰頁面,點擊關閉,彈出matk1對話框。
?
?
總結
以上是生活随笔為你收集整理的Windows核心编程 第23章 结束处理程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows PE第6章 栈与重定位表
- 下一篇: Windows核心编程 第2 4章 异常