首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Win32 結構化異常處理 (SEH) 深度探秘 (上):核心機制、編譯器實現與預設處理器

     編輯:關於C++

SEH 核心觀念:回呼函數與註冊鏈表

Win32 SEH 本質是:異常發生時,OS 呼叫用戶定義的回呼函數。回呼原型:

EXCEPTION_DISPOSITION __cdecl _except_handler(
    EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    CONTEXT *ContextRecord,
    void *DispatcherContext);
  • EXCEPTION_RECORD:異常代碼 (如 0xC0000005)、位址、參數。
  • CONTEXT:異常瞬間的寄存器快照 (EIP、ESP、EAX...),可修改以修復錯誤。
  • EXCEPTION_REGISTRATION:鏈表節點,含 prev (前一節點) 與 handler (回呼指標)。

線程資訊塊 (TIB/TEB) 的 FS:[0] 指向鏈表頭。OS 遍歷鏈表,尋找願意處理異常的回呼 (返回 ExceptionContinueExecution);拒絕處理則返回 ExceptionContinueSearch 繼續向下。

最小範例:手工安裝 SEH 幀

內嵌組語建立 EXCEPTION_REGISTRATION 於堆疊,修改 FS:[0],故意觸發存取違例 (寫入位址 0),回呼中修正 EAX 指向合法記憶體並返回 ExceptionContinueExecution,指令重試成功。展示 SEH 最原始運作面貌。

多層處理與展開:EH_UNWINDING 旗標

若內層回呼拒絕處理,外層處理後,系統會二次遍歷鏈表,旗標帶 EH_UNWINDING (2) 再次呼叫內層回呼,給予清理機會 (呼叫解構函數、執行 __finally)。此機制確保非正常退出時資源正確釋放。

預設處理器:BaseProcessStart 與 UnhandledExceptionFilter

進程啟動時 BaseProcessStart 以 __try/__except 包裹入口點,安裝預設處理器於鏈表尾。未處理異常時呼叫 UnhandledExceptionFilter:顯示錯誤對話框、支援 JIT 除錯、或直接終止進程。服務進程則呼叫 ExitThread 僅終止故障線程。

編譯器層 SEH:__except_handler3 與 Scope Table

Visual C++ 封裝 OS SEH,提供 __try/__except 模型:

  • 單一 EXCEPTION_REGISTRATION 對應整個函數,handler 固定指向 __except_handler3。
  • 擴展幀包含 scopetable (過濾器/處理器地址陣列)、trylevel (當前嵌套層級)、_ebp (上一層 EBP)。
  • __except_handler3 依 trylevel 索引 scopetable,呼叫過濾器運算式;若返回 EXCEPTION_EXECUTE_HANDLER,呼叫 __global_unwind2 展開幀,再呼叫 __local_unwind2 執行區域清理,最後跳轉至 __except 區塊 (不返回)。
  • GetExceptionInformation/GetExceptionCode 為編譯器內建函數,直接讀取幀中預留的 EXCEPTION_POINTERS。

ShowSEHFrames:視覺化驗證

示範程式遍歷 FS:[0] 鏈表,列印每個幀位址、處理器、scopetable 內容。輸出證實:多個函數共用 __except_handler3,最底層幀來自 CRT BaseProcessStart (位於 KERNEL32.dll)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved