国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

C++編譯器如何實現(xiàn)異常處理(1)

2019-11-17 05:16:14
字體:
供稿:網(wǎng)友
譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 strUCt EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* PRev; DWord handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。
譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 struct EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* prev; DWORD handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();
之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 struct EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* prev; DWORD handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 struct EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* prev; DWORD handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/
注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 struct EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* prev; DWORD handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。譯者注:本文在網(wǎng)上已經(jīng)有幾個譯本,但都不完整,所以我決定自己把它翻譯過來。雖然力求信、雅、達,但鑒于這是我的第一次翻譯經(jīng)歷,不足之處敬請諒解并指出。與傳統(tǒng)語言相比,C++的一項革命性創(chuàng)新就是它支持異常處理。傳統(tǒng)的錯誤處理方式經(jīng)常滿足不了要求,而異常處理則是一個極好的替代解決方案。它將正常代碼和錯誤處理代碼清楚的劃分開來,程序變得非常干凈并且輕易維護。本文討論了編譯器如何實現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機制。本文還提供了一個用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個,你只需要調(diào)用下面這個函數(shù): install_my_handler();
之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運行,都將由我的異常處理庫來治理。與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實現(xiàn)異常處理。這意味著每一個編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺崿F(xiàn)它。下面我會描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實現(xiàn)方式是以windows系統(tǒng)的結(jié)構(gòu)化異常處理(SEH)②為基礎(chǔ)的。

結(jié)構(gòu)化異常處理—概述

在本文的討論中,我認(rèn)為異常或者是被明確的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時會產(chǎn)生一個中斷,接下來控制權(quán)就會傳遞到操作系統(tǒng)的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列,進行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu)“EXCEPTION_REGISTRATION”,使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。 struct EXCEPTION_REGISTRATION{ EXCEPTION_REGISTRATION* prev; DWORD handler;}; 注冊時,只需要創(chuàng)建這樣一個結(jié)構(gòu),然后把它的地址放到FS段偏移0的位置上去就行了。下面這句匯編代碼演示了這一操作:mov FS:[0], exc_regp

prev字段用于建立一個EXCEPTION_REGISTRATION結(jié)構(gòu)的鏈表,每次注冊新的EXCEPTION_REGISTRATION時,我們都要把原來注冊的那個的地址存到prev中。那么,那個異常回調(diào)函數(shù)長什么樣呢?在excpt.h中,windows定義了它的原形:

EXCEPTION_DISPOSITION (*handler)( _EXCEPTION_RECORD *ExcRecord, void* EstablisherFrame, _CONTEXT *ContextRecord, void* DispatcherContext); 不要管它的參數(shù)和返回值,我們先來看一個簡單的例子。下面的程序注冊了一個異常處理程序,然后通過除以零產(chǎn)生了一個異常。異常處理程序捕捉了它,打印了一條消息就完事大吉并退出了。

#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; //不會運行到這 } int g_div = 0; void bar() { //初始化一個EXCEPTION_REGISTRATION結(jié)構(gòu) EXCEPTION_REGISTRATION reg, *preg = ® reg.handler = (DWORD)myHandler; //取得當(dāng)前異常處理鏈的“頭” DWORD prev; _asm { mov EAX, FS:[0] mov prev, EAX } reg.prev = (EXCEPTION_REGISTRATION*) prev; //注冊! _asm { mov EAX, preg mov FS:[0], EAX } //產(chǎn)生一個異常 int j = 10 / g_div; //異常,除零溢出 } int main() { bar(); return 0; } /*-------輸出------------------- In the exception handler Just a demo. exiting... ---------------------------------*/注重EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個結(jié)點更低的內(nèi)存地址上,Windows對此有嚴(yán)格要求,達不到的話,它就會馬上終止進程。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 利辛县| 三亚市| 漾濞| 大方县| 南陵县| 焦作市| 大同县| 蒲城县| 安平县| 腾冲县| 望江县| 大连市| 凤阳县| 龙南县| 鄂托克旗| 阿坝| 宜昌市| 报价| 昭觉县| 堆龙德庆县| 新晃| 鹤壁市| 蒙阴县| 时尚| 抚松县| 海伦市| 泰来县| 泗水县| 浦江县| 梁河县| 都安| 通许县| 泰和县| 柯坪县| 漳平市| 尖扎县| 南京市| 和林格尔县| 龙里县| 睢宁县| 集安市|