怎樣使C++編譯器實(shí)現(xiàn)異常處理
在介紹C++編譯器的前提下,先要介紹一下什么是C++編譯器,C++編譯器是一個(gè)與標(biāo)準(zhǔn)化C++高度兼容的編譯環(huán)境,這點(diǎn)對于編譯可移植的代碼十分重要,編譯器對不同的CPU會進(jìn)行不同的優(yōu)化。
它將正常代碼 和錯(cuò)誤處理代碼清晰的劃分開來,程序變得非常干凈并且容易維護(hù)。本文討論了編譯器如何實(shí)現(xiàn)異常處理。我將假定你已經(jīng)熟悉異常處理的語法和機(jī)制。本文還提供 了一個(gè)用于VC++的異常處理庫,要用庫中的處理程序替換掉VC++提供的那個(gè),你只需要調(diào)用下面這個(gè)函數(shù):
- install_my_handler();
之后,程序中的所有異常,從它們被拋出到堆棧展開(stack unwinding),再到調(diào)用catch塊,最后到程序恢復(fù)正常運(yùn)行,都將由我的異常處理庫來管理。 與其它C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定編譯器應(yīng)該如何來實(shí)現(xiàn)異常處理。這意味著每一個(gè)編譯器的提供商都可以用它們認(rèn)為恰當(dāng)?shù)姆绞絹韺?shí)現(xiàn)它。
下面我會 描述一下VC++是怎么做的,但即使你使用其它的編譯器或操作系統(tǒng)①,本文也應(yīng)該會是一篇很好的學(xué)習(xí)材料。VC++的實(shí)現(xiàn)方式是以windows系統(tǒng)的結(jié) 構(gòu)化異常處理(SEH)②為基礎(chǔ)的。
在本文的討論中,我認(rèn)為異?;蛘呤潜幻鞔_的拋出的,或者是由于除零溢出、空指針訪問等引起的。當(dāng)它發(fā)生時(shí)會產(chǎn)生一個(gè)中斷。接下來控制權(quán)就會傳遞到操作系統(tǒng) 的手中。操作系統(tǒng)將調(diào)用異常處理程序,檢查從異常發(fā)生位置開始的函數(shù)調(diào)用序列。
進(jìn)行堆棧展開和控制權(quán)轉(zhuǎn)移。Windows定義了結(jié)構(gòu) "EXCEPTION_REGISTRATION",使我們能夠向操作系統(tǒng)注冊自己的異常處理程序。
- #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; //不會運(yùn)行到這
- }
- int g_div = 0;
- void bar()
- {
- //初始化一個(gè)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)生一個(gè)異常
- int j = 10 / g_div; //異常,除零溢出
- }
- int main()
- {
- bar();
- return 0;
- }
注意EXCEPTION_REGISTRATION必須定義在棧上,并且必須位于比上一個(gè)結(jié)點(diǎn)更低的內(nèi)存地址上,windows對此有嚴(yán)格要求,達(dá)不到的話,它就會立刻終止進(jìn)程。
【編輯推薦】