溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++編譯器是怎樣實(shí)現(xiàn)異常處理

發(fā)布時(shí)間:2021-11-24 09:57:48 來(lái)源:億速云 閱讀:136 作者:柒染 欄目:編程語(yǔ)言

本篇文章為大家展示了C++編譯器是怎樣實(shí)現(xiàn)異常處理,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

由于C++編譯器裝程序太多,此處無(wú)法上傳,所以大家有communitysever的可以從里面獲得然后反編譯為自己所用。

與理則是一個(gè)極好的替代解決方案。它將正常代碼 和錯(cuò)誤處理代碼清晰的劃分開(kāi)來(lái),程序變得非常干凈并且容易維護(hù)。本文討論了編譯器如何實(shí)現(xiàn)異常處理。我將假定你已經(jīng)熟悉C++編譯器處理的語(yǔ)法和機(jī)制。本文還提供 了一個(gè)用于VC++的異常處理庫(kù),要用庫(kù)中的處理程序替換掉VC++提供的那個(gè),你只需要調(diào)用下面這個(gè)函數(shù):

struct EXCEPTION_REGISTRATION  {      EXCEPTION_REGISTRATION* prev;      DWORD handler;  };

之后,程序中的所有異常,從它們被拋出到堆棧展開(kāi)(stack unwinding),再到調(diào)用catch塊,***到程序恢復(fù)正常運(yùn)行,都將由我的異常處理庫(kù)來(lái)管理。
與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒(méi)有規(guī)定編譯器應(yīng)該如何來(lái)實(shí)現(xiàn)異常處理。這意味著每一個(gè)編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹?lái)實(shí)現(xiàn)它。下面我會(huì) 描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會(huì)是一篇很好的學(xué)習(xí)材料。VC++的實(shí)現(xiàn)方式是以windows系統(tǒng)的結(jié) 構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

struct EXCEPTION_REGISTRATION  {      EXCEPTION_REGISTRATION* prev;      DWORD handler;  };

在本文的討論中,我認(rèn)為異?;蛘呤潜幻鞔_的拋出的,或者是由于除零溢出、空指針訪問(wèn)等引起的。當(dāng)它發(fā)生時(shí)會(huì)產(chǎn)生一個(gè)中斷,接下來(lái)控制權(quán)就會(huì)傳遞到操作系統(tǒng) 的手中。操作系統(tǒng)將調(diào)用異常處理程序,C++編譯器異常發(fā)生位置開(kāi)始的函數(shù)調(diào)用序列,進(jìn)行堆棧展開(kāi)和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu) "EXCEPTION_REGISTRATION",使我們能夠向操作系統(tǒng)注冊(cè)自己的異常處理程序。

#include   #include    using std::cout;   using std::endl;    struct EXCEPTION_REGISTRATION   {       EXCEPTION_REGISTRATION* prev;       DWORD handler;   };    EXCEPTION_DISPOSITION myHandler(       _EXCEPTION_RECORD *ExcRecord,       void * EstablisherFrame,       _CONTEXT *ContextRecord,       void * DispatcherContext)   {       cout << "In the exception handler" << endl;       cout << "Just a demo. exiting..." << endl;       exit(0);       return ExceptionContinueExecution; //不會(huì)運(yùn)行到這   }    int  g_div = 0;    void bar()   {       //初始化一個(gè)EXCEPTION_REGISTRATION結(jié)構(gòu)       EXCEPTION_REGISTRATION reg, *preg = &reg;        reg.handler = (DWORD)myHandler;        //取得當(dāng)前異常處理鏈的"頭"       DWORD prev;       _asm       {           mov EAX, FS:[0]           mov prev, EAX       }       reg.prev = (EXCEPTION_REGISTRATION*) prev;        //注冊(cè)!       _asm       {           mov EAX, preg           mov FS:[0], EAX       }        //產(chǎn)生一個(gè)異常       int  j = 10 / g_div;  //異常,除零溢出   }    int  main()   {       bar();       return 0;   }    /*-------輸出-------------------   In the exception handler   Just a demo. exiting...

C++編譯器用于建立一個(gè)EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊(cè)新的EXCEPTION_REGISTRATION時(shí),我們都要把原來(lái)注冊(cè)的那個(gè)的地址存到prev中。 那么,那個(gè)異?;卣{(diào)函數(shù)長(zhǎng)什么樣呢?在excpt.h中,windows定義了它的原形: 注意EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個(gè)結(jié)點(diǎn)更低的內(nèi)存地址上,windows對(duì)此有嚴(yán)格要求,達(dá)不到的話,它就會(huì)立刻終止進(jìn)程。

上述內(nèi)容就是C++編譯器是怎樣實(shí)現(xiàn)異常處理,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI