日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

未处理异常和C++异常——Windows核心编程学习手札之二十五

發布時間:2025/4/16 c/c++ 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 未处理异常和C++异常——Windows核心编程学习手札之二十五 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

未處理異常和C++異常

——Windows核心編程學習手札之二十五

當一個異常過濾器返回EXCEPTION_CONTINUE_SEARCH標識符時是告訴系統繼續上溯調用樹,尋找另外的異常過濾器,但當每個過濾器都返回EXCEPTION_CONTINUE_SEARCH標識符,出現了所謂“未處理異常”。

每個線程開始執行,實際是利用kernel32.dll中的一個函數來調用BaseProcessStartBaseThreadStart,這兩個函數實際是一樣的,區別在于一個函數用于進程的主線程(primary thread):

?????? VOID BaseProcessStart(PPROCESS_START_ROUTINE pfnStartAddr){

???????????????????? __try{

?????????????????????????????????? ExitThread((pfnStartAddr)());

???????????????????? }

???????????????????? __except(UnhandledExceptionFilter(GetExceptionInfomation())){

??????????????????????????? ExitProcess(GetExceptionCode());

???????????????????? }

??????????? //note:we never get here

?????? }

另一個函數用于進程的所有輔助線程(Secondary thread):

?????? VOID BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr,PVOID pvParam){

???????????????????? __try{

?????????????????????????????????? ExitThread((pfnStartAddr)( pvParam));

???????????????????? }

???????????????????? __except(UnhandledExceptionFilter(GetExceptionInfomation())){

??????????????????????????? ExitProcess(GetExceptionCode());

???????????????????? }

??????????? //note:we never get here

?????? }

這兩個函數都包含一個SHE框架,每個函數都有一個try塊,并從這個try塊里調用主線程或輔助線程的進入點函數。當線程引發一個異常時,所有過濾器都返回EXCEPTION_CONTINUE_SEARCH時,將會自動調用一個由系統提供的特殊過濾器函數:

?????? LONG UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)

這個函數負責顯示一個消息框,指出有一個進程的線程存在未處理的異常,并且能讓用戶結束或調試這個進程。在消息框的異常描述之后,提供用戶兩個選擇:

1)選擇“ok”按鈕,將導致UnhandledExceptionFilter返回EXCEPTION_CONTINUE_SEARCH,這將引起全局展開,所有的finally塊都要執行,然后BaseProcessStartBaseThreadStart中的處理程序執行。這兩個處理程序都是ExitProcess,退出進程,退出的代碼是異常代碼,這是進程的線程結束了進程本身不是操作系統,意味這程序員可以控制這種行為并改變它。

2)選擇“Cancel”按鈕,UnhandledExceptionFilter試圖加載一個調試程序,并將這個調試程序掛接在進程上,通過將調試程序附在進程上,可以檢查全局、局部和靜態變量的狀態,設置斷點,檢查調用樹,重新啟動進程,以及調試一個進程可以做的任何事情。

注意:上面是在用戶方式(user-mode)下的程序開發,對于運行在內核方式(kernel-mode)出現未處理異常,未處理異常是在操作系統中或更可能在設備驅動程序中,而不是在應用程序中,這樣的未處理異常表示一個嚴重的程序錯誤(bug)!如果一個低級虛擬內存函數產生一個異常,系統查找是否有內核方式異常過濾器準備處理這個異常,如果系統找不到,則異常是未處理的,如果一個未處理異常發生在內核方式,讓系統繼續運行是不安全的,所以系統在這種情況下不會調用UnhandledExceptionFilter函數,而是顯示所謂的藍屏死機(Blue Screen of Death),顯示畫屏切換到只包含文本的藍屏視頻方式,并且計算機被停機(balt),顯示的文本告訴是哪個設備驅動程序被加載,并且該模塊中包含引發未處理異常的代碼。

當程序員選擇cancel按鈕時,告訴UnhandledExceptionFilter函數對進程進行調試,隨時將調試程序連接到任何進程的能力稱為即時調試(Just-in-time Debugging)。在內部,UnhandledExceptionFilter調用調試程序,需要查看下面的注冊表子關鍵字:

?????? HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/WindowsNT/

CurrentVersion/AeDebug

該關鍵字里,有一個Debugger的數值,安裝Visual Studio時被設置成下面的值:

?????? C:/Program Filese/Microsoft Visual Studio/Common/MSDev98/Bin/msdev.exe

?????????????????????????? -p %ld? –e %ld

windows98中,這些值不存放在注冊表中,而是存放在Win.ini文件中。

這個值告訴系統要將哪個程序(這里是msdev.exe)作為調試程序運行,當然也可以選擇其他調試程序。UnhandledExceptionFilter還在命令行里向調試程序傳遞兩個參數,第一個參數是被調試進程ID;第二個參數規定一個可繼承的手工復位事件,這個事件是由UnhandledExceptionFilter按無信號狀態建立的,廠商必須實現自己的調試程序,這樣才能認識指定進程ID和事件句柄的-p-e選項。

在進程ID和事件句柄都合并到這個串中后,UnhandledExceptionFilter通過調用CreateProcess來執行調試程序,這是,調試程序進程開始運行并檢查它的命令行參數,如果存在-p選項,調試程序取得進程ID,并通過調用DebugActiveProcess將自身掛接到該進程上:

?????? BOOL DebugActiveProcess(DWORD dwProcessID)

一旦調試程序完成自身的掛接,操作系統將被調試者(debuggee)的狀態通報給調試程序。在調試程序完全初始化后,要再檢查它的命令行,找-e選項,如該項存在,調試程序取得相應事件句柄并調用SetEvent

另外,不必在調試進程之前等待異常的出現,可以隨時將一個調試程序連接在任何進程上,只需運行MSDEV –p PID,其中PID是要調試的進程的ID,實際在Windows2000Task Manager里選擇一個進程,并選擇debug菜單,就將引起Task Manager去查看前面的注冊表子關鍵字,調用CreateProcess,并傳遞所選定的進程ID作為參數,在這里,Task Manage為事件句柄傳送0值。

如果異常發生時,不想在屏幕上顯示消息框,有下面幾個方法:

1)強制進程終止運行

為防止UnhandledExceptionFilter顯示異常消息框,可以調用SetErrorMode函數,并向它傳遞一個SEM_NOGPFAULTERRORBOX標識符:

?????? UNINT SetErrorMode(UINT fuErrorMode)

當調用UnhandledExceptionFilter函數來處理異常時,看到已經設置了這個標志,就立即返回EXCEPT_EXECUTE_HANDLER,這將導致全局展開并執行BaseProcessStartBaseThreadStart中的處理程序,該處理程序結束進程。

2)包裝一個線程函數

在主線程進入點函數 mainwmainWinMainwWinMain)的整個內容安排一個try-except塊,保證異常過濾器的結果值總是EXCEPT_EXECUTE_HANDLER,這樣就保證異常總能得到處理,防止系統再調用UnhandledExceptionFilter函數。缺點是只能捕捉主線程中發生的異常,而其他輔助線程則不能覆蓋。

3)包裝所有線程函數

Windows提供了SetUnhandledExceptionFilter函數可以按SHE格式包裝所有線程函數。

?????? PTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(

??????????????????????????? PTOP_LEVEL_EXCEPTION_FILTER pTopLevelExceptionFilter);

在進程調用這個函數后,進程的任何線程發生一個未處理異常,就會導致調用程序自己的異常過濾器,需要將這個過濾器地址作為參數傳遞給SetUnhandledExceptionFilter。過濾器函數原型是:

?????? LONG UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)

3)自動調用調試程序

在設置調試程序的注冊表同一個關鍵字里,有個Auto值,該值用來規定UnhandledExceptionFilter是應該顯示消息框還是僅啟動調試程序,如果Auto設置為1UnhandledExceptionFilter就不顯示消息框向用戶報告異常,而是立即調用調試程序,如設置為0,就按照上面所說的。

UnhandledExceptionFilter函數的內部執行情況:

1)如果發生一個存取違規并且是由于試圖寫內存(相對于讀內存)引起的,系統要查看是不是要修改一個exe模塊或dll模塊中的資源,默認下資源是只讀的,試圖修改資源會引起存取異常。然而16Windows允許修改資源,從兼容性考慮,32位和64位也應允許修改資源,所以當想要修改資源時,UnhandledExceptionFilter調用VirtualProtect,將資源頁上的保護改成PAGE_READWRITE,并返回EXCEPTION_CONTINUE_EXECUTION

2)如果已經調用了SetUnhandledExceptionFilter指定自己的過濾器,UnhandledExceptionFilter就調用指定的過濾器,如果自己的過濾器返回EXCEPTION_EXECUTE_HANDLEREXECEPTION_CONTINUE_EXECUTIONUnhandledExceptionFilter就將這個值返回給系統,如果沒有設置自己的未處理異常過濾器,或自己的未處理異常過濾器返回EXCEPTION_CONTINUE_SEARCH,則進入第3步;

3)如果進程是在調試程序下運行,就返回EXCEPTION_CONTINUE_SEARCH。調試程序顯示一個消息框并運行調試進程(IsDebuggerPresent函數用來確定一個進程是否正在被調試);

4)如果進程中一個線程以SEM_NOGPFAULTERRORBOX標志為參數調用SetErrorCodeUnhandledExceptionFilter就返回EXCEPTION_EXECUTE_HANDLER

5)如果進程在一個作業job里并且作業的限制信息設定了JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION標志,則UnhandledExceptionFilter返回EXCEPTION_EXECUTE_HANDLER

6UnhandledExceptionFilter查閱注冊表并取出Auto值,如果是1,到第7步,如是0,則向用戶顯示一個消息框;

7UnhandledExceptionFilter產生調試程序,首先調用CreateEvent建立一個無信號的、手工復位的事件,這個事件的句柄可繼承,然后從注冊表中取出Debugger值,調用sprintf把它粘帖到進程ID(通過調用GetCurrentProcessID函數得到)和事件句柄里。STARTUPINFOlpDesktop成員也設置成”Winsta0//Default”,這樣調試程序就出現在交互式桌面上。

8)當調試程序完成初始化,就設置事件句柄,這將喚醒UnhandledExceptionFilter中的線程,這樣進程就在調試程序下運行,UnhandledExceptionFilter返回EXCEPTION_CONTINUE_SEARCH

SHE(結構化異常處理)可用于任何編程語言的操作系統設施,而C++異常只能用于編寫C++代碼。如果是編寫C++程序,應使用C++異常處理而不是結構化異常處理,理由是C++異常處理是語言的一部分,編譯器知道C++類對象是什么,也就是說編譯器能夠自動生成代碼來調用C++對象析構函數,保證對象的清除。

不過,Microsoft Visual C++編譯器也利用了操作系統的SHE實現了C++異常處理,所以當建立一個C++try塊時,編譯器就生成一個SHE__try塊,一個C++catch測試變成一個SHE異常過濾器,并且catch中的代碼變成SHE__except塊中的代碼,實際上,C++throw語句,編譯器生成windows對應的RaiseException函數的調用,用于throw語句的變量傳遞給RaiseException作為附加的參數,如上,C++異常在內部是由SHE實現的。

正常情況下,C++異常處理不能使程序從硬件異常中恢復,硬件違規就是存取違規或零作除數這種異常,但microsoft已經對其編譯器增加了這種支持能力。

總結

以上是生活随笔為你收集整理的未处理异常和C++异常——Windows核心编程学习手札之二十五的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产第56页| 国产福利视频导航 | 99re色| 美少妇av | 蜜臀视频在线观看 | 一区二区三区人妻 | 日本黄色网页 | 在线免费观看av网址 | 国产视频一区在线 | 特级西西人体 | 19韩国主播青草vip | 无码任你躁久久久久久久 | 蜜桃视频成人在线观看 | 日本天堂网在线观看 | 国产拍拍拍 | 日本xxxx18| 波多野结衣理论片 | av片在线观看免费 | 亚洲在线天堂 | 在线观看欧美成人 | 2019亚洲男人天堂 | 后入内射无码人妻一区 | 国产精品8| 麻豆精品免费 | 日韩在线第三页 | 日韩中文欧美 | 香蕉黄色片 | 原神女裸体看个够无遮挡 | 国产精品视频福利 | 国产成人精品免费网站 | 少妇一级淫免费播放 | 日韩av影视大全 | 99热日本 | 丰满圆润老女人hd | 自拍偷拍精品视频 | 激情网站在线观看 | 日本少妇一区 | 国内三级在线 | 黄色片一区二区三区 | 成年人在线免费观看网站 | 五月天看片| www.色偷偷 | 日本欧美不卡 | 去毛片 | 上原亚衣av一区二区三区 | 每日更新在线观看av | 免费欧美一级视频 | va在线看| 成人免费性生活视频 | 沈樵精品国产成av片 | 欧美资源在线 | 秋霞影院午夜丰满少妇在线视频 | 99色网| 激情综合婷婷 | 亚洲精品二区 | 无人码人妻一区二区三区免费 | 日本精品免费一区二区三区 | 久久精品无码一区二区三区 | 亚洲色图 美腿丝袜 | 亚洲成熟丰满熟妇高潮xxxxx | 成人在线免费观看视频 | 久草热在线视频 | 亚洲玖玖爱 | 在线观看你懂的网址 | 亚洲第一av在线 | 五月天丁香网 | 久久久噜噜噜久久中文字幕色伊伊 | 韩国午夜影院 | 午夜免费播放观看在线视频 | 性欧美videos另类hd | 午夜寂寞自拍 | 中文字幕成人动漫 | 亚洲色图在线视频 | 精品人妻伦一区二区三区久久 | av 日韩 人妻 黑人 综合 无码 | 精品少妇人妻av一区二区 | 九九热精品免费视频 | 日韩欧美理论 | 久久视频免费观看 | 精品国产乱码一区二区 | 久久午夜免费视频 | 黄色一级免费片 | 欧美激情伊人 | 精品成人免费一区二区在线播放 | 亚洲精品网站在线观看 | 少妇人妻互换不带套 | 日韩视频不卡 | 都市激情 亚洲 | 国产精欧美一区二区三区白种人 | 找个毛片看看 | 黄色小说图片视频 | 国产美女视频一区二区 | 激情五月av | 国产男女猛烈无遮挡a片漫画 | 伦理片波多野结衣 | 五月婷在线观看 | 午夜激情在线视频 | 国产在线视视频有精品 | 亚洲爽爆 |