亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中異常機制的實現機制詳解

2020-05-23 13:26:45
字體:
來源:轉載
供稿:網友

前言

異常就是運行時出現出現的不正常(沒說一樣),例如系統運行時耗盡了內存或遇到意外的非法輸入。本文詳細介紹了關于C++中異常機制實現機制的相關內容,下面話不多說了,來一起看看詳細的介紹吧。

1、C函數的調用和返回

要理解C++異常機制實現之前,首先要了解一個函數的調用和返回機制,這里面就要涉及到ESP和EBP寄存器。我們先看一下函數調用和返回的流程。

下面是按調用約定__stdcall 調用函數test(int p1,int p2)的匯編代碼
假設執行函數前堆棧指針ESP為NN
push p2 ;參數2入棧, ESP -= 4h , ESP = NN - 4h
push p1 ;參數1入棧, ESP -= 4h , ESP = NN - 8h
call test ;壓入返回地址 ESP -= 4h, ESP = NN - 0Ch 
{
push ebp ;保護先前EBP指針, EBP入棧, ESP-=4h, ESP = NN - 10h
mov ebp, esp ;設置EBP指針指向棧頂 NN-10h
mov eax, dword ptr [ebp+0ch] ;ebp+0ch為NN-4h,即參數2的位置
mov ebx, dword ptr [ebp+08h] ;ebp+08h為NN-8h,即參數1的位置
sub esp, 8 ;局部變量所占空間ESP-=8, ESP = NN-18h
...
add esp, 8 ;釋放局部變量, ESP+=8, ESP = NN-10h
pop ebp ;出棧,恢復EBP, ESP+=4, ESP = NN-0Ch
ret 8 ;ret返回,彈出返回地址,ESP+=4, ESP=NN-08h, 后面加操作數8為平衡堆棧,ESP+=8,ESP=NN, 恢復進入函數前的堆棧.
}

函數棧架構主要承載著以下幾個部分:

  1、傳遞參數:通常,函數的調用參數總是在這個函數??蚣艿淖铐敹恕?/p>

  2、傳遞返回地址:告訴被調用者的 return 語句應該 return 到哪里去,通常指向該函數調用的下一條語句(代碼段中的偏移)。

  3、存放調用者的當前棧指針:便于清理被調用者的所有局部變量、并恢復調用者的現場。

  4、存放當前函數內的所有局部變量:記得嗎?剛才說過所有局部和臨時變量都是存儲在棧上的?! ?/p>

C++,異常機制  

2、C++函數調用

首先澄清一點,這里說的 “C++ 函數”是指:

  1、該函數可能會直接或間接地拋出一個異常:即該函數的定義存放在一個 C++ 編譯(而不是傳統 C)單元內,并且該函數沒有使用“throw()”異常過濾器

  2、該函數的定義內使用了 try 塊。

以上兩者滿足其一即可。為了能夠成功地捕獲異常和正確地完成?;赝耍╯tack unwind),編譯器必須要引入一些額外的數據結構和相應的處理機制。我們首先來看看引入了異常處理機制的棧框架大概是什么樣子:

C++,異常機制  

由圖2可見,在每個 C++ 函數的棧框架中都多了一些東西。仔細觀察的話,你會發現,多出來的東西正好是一個 EXP 類型的結構體。進一步分析就會發現,這是一個典型的單向鏈表式結構:

  piPrev 成員指向鏈表的上一個節點,它主要用于在函數調用棧中逐級向上尋找匹配的 catch 塊,并完成棧回退工作。

  piHandler 成員指向完成異常捕獲和棧回退所必須的數據結構(主要是兩張記載著關鍵數據的表:“try”塊表:tblTryBlocks 及“?;赝吮?rdquo;:tblUnwind)。

  nStep 成員用來定位 try 塊,以及在棧回退表中尋找正確的入口。

需要說明的是:編譯器會為每一個“C++ 函數”定義一個 EHDL 結構,不過只會為包含了“try”塊的函數定義 tblTryBlocks 成員。此外,異常處理器還會為每個線程維護一個指向當前異常處理框架的指針。該指針指向異常處理器鏈表的鏈尾,通常存放在某個 TLS 槽或能起到類似作用的地方。

3、?;赝耍╯tack unwind)

“棧回退”是伴隨異常處理機制引入 C++ 中的一個新概念,主要用來確保在異常被拋出、捕獲并處理后,所有生命期已結束的對象都會被正確地析構,它們所占用的空間會被正確地回收。下面我們就來具體看看編譯器是如何實現棧回退機制的:

C++,異常機制  

圖中的“FuncUnWind”函數內,所有真實代碼均以黑色和藍色字體標示,編譯器生成的代碼則由灰色和橙色字體標明。此時,在圖里給出的 nStep 變量和 tblUnwind 成員作用就十分明顯了。

nStep 變量用于跟蹤函數內局部對象的構造、析構階段。再配合編譯器為每個函數生成的 tblUnwind 表,就可以完成退棧機制。表中的 pfnDestroyer 字段記錄了對應階段應當執行的析構操作(析構函數指針);pObj 字段則記錄了與之相對應的對象 this 指針偏移。將 pObj 所指的偏移值加上當前??蚣芑罚‥BP),就是要代入 pfnDestroyer 所指析構函數的 this 指針,這樣即可完成對該對象的析構工作。而 nNextIdx 字段則指向下一個需要析構對象所在的行(下標)。

在發生異常時,異常處理器首先檢查當前函數??蚣軆鹊?nStep 值,并通過 piHandler 取得 tblUnwind[] 表。然后將 nStep 作為下標帶入表中,執行該行定義的析構操作,然后轉向由 nNextIdx 指向的下一行,直到 nNextIdx 為 -1 為止。在當前函數的?;赝斯ぷ鹘Y束后,異常處理器可沿當前函數??蚣軆?piPrev 的值回溯到異常處理鏈中的上一節點重復上述操作,直到所有回退工作完成為止。

值得一提的是,nStep 的值完全在編譯時決定,運行時僅需執行若干次簡單的整形立即數賦值(通常是直接賦值給CPU里的某個寄存器)。此外,對于所有內部類型以及使用了默認構造、析構方法(并且它的所有成員和基類也使用了默認方法)的類型,其創建和銷毀均不影響 nStep 的值。

注意:如果在?;赝说倪^程中,由于析構函數的調用而再次引發了異常(異常中的異常),則被認為是一次異常處理機制的嚴重失敗。此時進程將被強行禁止。為防止出現這種情況,應在所有可能拋出異常的析構函數中使用“std::uncaught_exception()”方法判斷當前是否正在進行?;赝耍矗捍嬖谝粋€未捕獲或未完全處理完畢的異常)。如是,則應抑制異常的再次拋出。

4、異常捕獲

一個異常被拋出時,就會立即引發 C++ 的異常捕獲機制:

C++,異常機制  

在上一小節中,我們已經看到了 nStep 變量在跟蹤對象構造、析構方面的作用。實際上 nStep 除了能夠跟蹤對象創建、銷毀階段以外,還能夠標識當前執行點是否在 try 塊中,以及(如果當前函數有多個 try 塊的話)究竟在哪個 try 塊中。這是通過在每一個 try 塊的入口和出口各為 nStep 賦予一個唯一 ID 值,并確保 nStep 在對應 try 塊內的變化恰在此范圍之內來實現的。

在具體實現異常捕獲時,首先,C++ 異常處理器檢查發生異常的位置是否在當前函數的某個 try 塊之內。這項工作可以通過將當前函數的 nStep 值依次在 piHandler 指向tblTryBlocks[] 表的條目中進行范圍為 [nBeginStep, nEndStep) 的比對來完成。

例如:若圖4 中的 FuncB 在 nStep == 2 時發生了異常,則通過比對 FuncB 的 tblTryBlocks[] 表發現 2∈[1, 3),故該異常發生在 FuncB 內的第一個 try 塊中。

其次,如果異常發生的位置在當前函數中的某個 try 塊內,則嘗試匹配該 tblTryBlocks[] 相應條目中的 tblCatchBlocks[] 表。tblCatchBlocks[] 表中記錄了與指定 try 塊配套出現的所有 catch 塊相關信息,包括這個 catch 塊所能捕獲的異常類型及其起始地址等信息。

若找到了一個匹配的 catch 塊,則復制當前異常對象到此 catch 塊,然后跳轉到其入口地址執行塊內代碼。

否則,則說明異常發生位置不在當前函數的 try 塊內,或者這個 try 塊中沒有與當前異常相匹配的 catch 塊,此時則沿著函數??蚣苤?piPrev 所指地址(即:異常處理鏈中的上一個節點)逐級重復以上過程,直至找到一個匹配的 catch 塊或到達異常處理鏈的首節點。對于后者,我們稱為發生了未捕獲的異常,對于 C++ 異常處理器而言,未捕獲的異常是一個嚴重錯誤,將導致當前進程被強制結束。

5、拋出異常

接下來討論整個 C++ 異常處理機制中的最后一個環節,異常的拋出:

C++,異常機制  

在編譯一段 C++ 代碼時,編譯器會將所有 throw 語句替換為其 C++ 運行時庫中的某一指定函數,這里我們叫它 __CxxRTThrowExp(與本文提到的所有其它數據結構和屬性名一樣,在實際應用中它可以是任意名稱)。該函數接收一個編譯器認可的內部結構(我們叫它 EXCEPTION 結構)。這個結構中包含了待拋出異常對象的起始地址、用于銷毀它的析構函數,以及它的 type_info 信息。對于沒有啟用 RTTI 機制(編譯器禁用了 RTTI 機制或沒有在類層次結構中使用虛表)的異常類層次結構,可能還要包含其所有基類的 type_info 信息,以便與相應的 catch 塊進行匹配。

在圖中的深灰色框圖內,我們使用 C++ 偽代碼展示了函數 FuncA 中的 “throw myExp(1);” 語句將被編譯器最終翻譯成的樣子。實際上在多數情況下,__CxxRTThrowExp 函數即我們前面曾多次提到的“異常處理器”,異常捕獲和?;赝说雀黜椫匾ぷ鞫加伤鼇硗瓿伞?/p>

__CxxRTThrowExp 首先接收(并保存)EXCEPTION 對象;然后從 TLS:Current ExpHdl 處找到與當前函數對應的 piHandler、nStep 等異常處理相關數據;并按照前文所述的機制完成異常捕獲和?;赝恕S纱送瓿闪税?ldquo;拋出”->“捕獲”->“回退”等步驟的整套異常處理機制。

 6、總結

以上就是C++異常的實現原理,當然其他語言的異常捕獲機制也是同樣的思想實現異常處理的。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频自拍| 中文字幕亚洲综合| 亚洲第一区第二区| 欧美人与物videos| 日韩欧美国产一区二区| 亚洲美女在线视频| 精品国产999| 国产精品福利片| 亚洲精品第一国产综合精品| 亚洲成人精品在线| 91精品国产91久久久久久最新| 久久国产加勒比精品无码| 懂色av中文一区二区三区天美| 亚洲欧美精品一区二区| 欧美精品精品精品精品免费| 日日狠狠久久偷偷四色综合免费| 在线看日韩av| 国产亚洲精品久久久久久牛牛| 欧美日韩国产一中文字不卡| 久热精品在线视频| 中文字幕av一区二区三区谷原希美| 狠狠色噜噜狠狠狠狠97| 国产视频观看一区| 亚洲欧美中文日韩在线v日本| 亚洲美女av网站| xxxxxxxxx欧美| 欧美成人手机在线| 亚洲精品电影网站| 日韩av电影中文字幕| 91久久精品一区| 黑人狂躁日本妞一区二区三区| 亚洲欧美国产高清va在线播| 激情成人中文字幕| 亚洲精品视频在线观看视频| 国外成人在线视频| 精品色蜜蜜精品视频在线观看| 国产成人精品久久亚洲高清不卡| 欧洲s码亚洲m码精品一区| 欧美成人午夜免费视在线看片| 国产精品一区二区久久精品| 精品国产精品三级精品av网址| 亚洲欧美日韩视频一区| 国产精品96久久久久久又黄又硬| 亚洲深夜福利在线| 亚洲区在线播放| 国产精品极品美女在线观看免费| 亚洲国产成人精品一区二区| 成人网在线免费观看| 亚洲免费精彩视频| 国产精品毛片a∨一区二区三区|国| 久久久久久久一| 中文欧美日本在线资源| 8x海外华人永久免费日韩内陆视频| 国产精品美女免费| 红桃视频成人在线观看| 欧美成人免费播放| 国产精品美女久久久久av超清| 国产精品久久久久久中文字| 色悠悠久久88| 在线视频亚洲欧美| 中文字幕亚洲在线| 97香蕉超级碰碰久久免费软件| 国产精品一区二区在线| 国产91色在线|免| 国产在线精品播放| 欧美日韩一区二区免费在线观看| 国产成人精品999| 尤物精品国产第一福利三区| 欧美网站在线观看| 久久久久久久一| 国产一区二区美女视频| 国产精品白嫩初高中害羞小美女| 国产一区二区三区网站| 欧美性xxxx极品高清hd直播| 日本久久91av| 亚洲精品mp4| 欧美激情亚洲自拍| 欧美一级黄色网| 欧美成年人网站| 欧美日本在线视频中文字字幕| 国产成人精品999| 欧美综合在线第二页| 中国日韩欧美久久久久久久久| 色综合色综合网色综合| 久久久www成人免费精品张筱雨| 亚洲最大的成人网| 欧美一级成年大片在线观看| 欧美激情图片区| 欧美午夜xxx| 91视频国产高清| 亚洲成人黄色在线| 欧美野外猛男的大粗鳮| 欧美成人免费全部| 国产精品揄拍500视频| 亚洲黄一区二区| 国产精品大片wwwwww| 亚洲成色777777女色窝| 在线观看亚洲区| 欧美激情亚洲另类| 在线播放精品一区二区三区| 亚洲男人的天堂在线| 国产精品免费观看在线| 久久影院中文字幕| 国产69精品久久久久99| 久久人人爽亚洲精品天堂| 在线a欧美视频| 91香蕉嫩草神马影院在线观看| 亚洲精品国产综合区久久久久久久| 日韩欧美在线观看| 91青草视频久久| 欧美日韩国产一区二区| 久久久久久国产精品久久| 亚洲深夜福利网站| 亚洲经典中文字幕| 久热在线中文字幕色999舞| 亚洲第一中文字幕在线观看| 久久69精品久久久久久国产越南| 国产精品pans私拍| 97精品欧美一区二区三区| 精品久久久久久久中文字幕| 亚洲大胆人体在线| 国产精品国产三级国产aⅴ9色| 久久免费视频观看| 久久久久久有精品国产| 日本免费久久高清视频| 久久97精品久久久久久久不卡| 4438全国成人免费| 成人免费淫片视频软件| 中文欧美在线视频| 久久中文字幕视频| 日韩av最新在线观看| 日韩小视频在线| 亚洲日本欧美中文幕| 亚洲深夜福利网站| 91精品国产综合久久男男| 亚洲在线观看视频网站| 日韩精品在线电影| 国内免费久久久久久久久久久| 欧美华人在线视频| 色综合久久中文字幕综合网小说| 欧美中文字幕在线视频| 欧美午夜女人视频在线| 日韩av中文字幕在线免费观看| 国自在线精品视频| 久久99久久亚洲国产| 成人精品一区二区三区电影黑人| 欧美激情一区二区三级高清视频| 欧美多人乱p欧美4p久久| 欧美性黄网官网| 日韩大胆人体377p| 97久久伊人激情网| 国产有码一区二区| 国产成人福利网站| 最近中文字幕mv在线一区二区三区四区| 亚洲天堂2020| 久久久亚洲福利精品午夜| 国产日韩av高清| 欧美日韩一区二区免费视频| 欧美黑人视频一区| 国产亚洲欧美一区| 91精品国产综合久久男男| 青青久久av北条麻妃黑人| 中文字幕精品国产| 91九色蝌蚪国产|