欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

VC中的異常處理

系統(tǒng) 1689 0

在讀《軟件調(diào)試》的十一章時(shí),感受到異常處理在VC中是十分重要的。以前自己寫(xiě)代碼或者是看身邊的人寫(xiě)的代碼都很少用到異常處理,但最近在工作中會(huì)接觸到老外牛人寫(xiě)的代碼,幾乎在每個(gè)關(guān)鍵的代碼塊都提供了異常處理,雖然在這些異常處理代碼中只是簡(jiǎn)單的將異常的相關(guān)信息寫(xiě)入Event Viewer,但這已經(jīng)對(duì)我們找到bug和了解系統(tǒng)運(yùn)行情況提供了很大的幫助。于是乎我把學(xué)習(xí)這一章的心得總結(jié)出來(lái),供大家分享。

首先我們看window為描述異常定義的數(shù)據(jù)結(jié)構(gòu) EXCEPTION_RECORD,具體如下

typedef struct _EXCEPTION_RECORD{

DWORD ExceptionCode; // 異常代碼

DWORD ExceptionFlags; // 異常標(biāo)志

struct _EXCEPTION_RECORD* ExceptionRecord; // 相關(guān)的另外一個(gè)異常

PVOID ExceptionAddress; // 異常發(fā)生地址

DWORD NumberParameters; // 參數(shù)數(shù)組中的元素個(gè)數(shù)

ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; // 參數(shù)數(shù)組

}

其中的ExcptionCode,我們應(yīng)當(dāng)非常熟悉了,最常見(jiàn)的為EXCEPTION_ACCESS_VIOLATION, 值為0xC0000005L, 就是非法訪問(wèn),我們遇到的大多數(shù)Crash問(wèn)題都是來(lái)源于此。


了解了異常的結(jié)構(gòu),下面我們看異常是如何分發(fā)的:

異常分發(fā)包括用戶態(tài)的異常分發(fā)和內(nèi)核態(tài)的異常分發(fā),這里只介紹用戶態(tài)的異常分發(fā)。KiDispatchException是個(gè)內(nèi)核函數(shù),它是分發(fā)windows異常的樞紐,它的函數(shù)原型為KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,

IN PKEXCEPTION_FRAME ExceptionFrame,

IN PKTRAP_FRAME TrapFrame,

IN KPPROCESSOR_MODE PreviousMode,

IN BOOLEN FirstChange);

其中的參數(shù)ExceptionRecord指的是上面我介紹的_EXCEPTION_RECORD結(jié)構(gòu)。其他的參數(shù)我就不詳細(xì)介紹了,我重點(diǎn)介紹一下最后的一個(gè)參數(shù)FirstChange,相信使用過(guò)windbg的同學(xué)們都會(huì)發(fā)現(xiàn)總能看到FirstChange這個(gè)參數(shù)吧,其實(shí)異常在分發(fā)過(guò)程中最多可以分發(fā)兩次,下圖是摘自《軟件調(diào)試》,清楚的顯示了kiDispatchException的分發(fā)異常的過(guò)程。其中左側(cè)是用戶態(tài)的,右側(cè)是內(nèi)核態(tài)的。

如上圖所示,當(dāng)變量FirstChange為T(mén)RUE時(shí),調(diào)用DbgkForwardException分發(fā)給調(diào)試子系統(tǒng),也就是當(dāng)存在調(diào)試器時(shí),分首先分發(fā)給調(diào)試器,所以當(dāng)使用windbg時(shí)我們常會(huì)發(fā)現(xiàn)First Change字段。如果函數(shù)DbgForwardException返回FALSE,那么就說(shuō)明沒(méi)有發(fā)現(xiàn)調(diào)試器,會(huì)調(diào)用DbgkForwardException進(jìn)行第二次分發(fā),這次分發(fā)會(huì)尋找異常的處理塊,一般就是__exception{}字段的代碼或是catch{}字段的代碼,等一會(huì)在介紹。如果這次仍然返回FALSE,就會(huì)調(diào)用ZwTerminateThread終止當(dāng)前的線程,會(huì)彈出對(duì)話框,里面包含一些異常的信息,這個(gè)也是很常見(jiàn)的。如果出現(xiàn)在內(nèi)核狀態(tài),那么就直接出現(xiàn)藍(lán)屏(BSOD)。

下面介紹一下結(jié)構(gòu)化異常處理(SEH)和向量化異常處理(VEH)

結(jié)構(gòu)化異常處理,從系統(tǒng)的角度來(lái)看,SEH是對(duì)windows操作系統(tǒng)中異常分發(fā)和處理機(jī)制的總稱,其實(shí)現(xiàn)遍布在windows系統(tǒng)的很多模塊和數(shù)據(jù)結(jié)構(gòu)中。從編程的角度來(lái)看,SEH是一套規(guī)范,利用這套規(guī)范,程序員可以編寫(xiě)處理代碼來(lái)復(fù)用系統(tǒng)的異常處理設(shè)施。可以理解為是操作系統(tǒng)的異常機(jī)制的對(duì)外接口,也就是如何在windows程序中使用windows系統(tǒng)的異常處理機(jī)制。(摘自《軟件調(diào)試》291頁(yè))

結(jié)構(gòu)化異常處理提供了終結(jié)處理(Termination Handling)和異常處理(Exception Handling)兩種功能。以VC++為例,終結(jié)處理的結(jié)構(gòu)如下

__try

{

// 被保護(hù)體

}

__finally

{

// 終結(jié)處理代碼
}

終結(jié)處理的用途是只要被保護(hù)體內(nèi)的代碼執(zhí)行了,除非是調(diào)用了ExitThread或ExitProcess,那么終結(jié)處理的代碼就一定會(huì)執(zhí)行。所以終結(jié)處理的這種特性,適合做資源的釋放工作,包括內(nèi)存的釋放,避免內(nèi)存泄露,以及狀態(tài)的恢復(fù),包括信號(hào)設(shè)置等,避免多線程出現(xiàn)死鎖。

終結(jié)處理的執(zhí)行過(guò)程有一點(diǎn)需要說(shuō)明,如果被保護(hù)體內(nèi)存在代碼return,那意味著退出函數(shù),這時(shí)終結(jié)塊是如何被執(zhí)行的呢?其實(shí)編譯器會(huì)定義一個(gè)局部變量來(lái)保存return的值,然后在目標(biāo)代碼中出入指令調(diào)用名為_(kāi)_local_unwind2的局部展開(kāi)函數(shù),來(lái)進(jìn)行調(diào)用finally塊的代碼。注:加雙下劃線的關(guān)鍵字是編譯器定義的。

下面我們看異常的處理方式:

__try

{

// 被保護(hù)的代碼塊

}

__except( 過(guò)濾表達(dá)式)

{

// 異常處理塊

}

是不是覺(jué)得眼熟,它與C++的異常處理很相似,C++的try-catch-throw結(jié)構(gòu)如下:

try {
// code that could throw an exception
}
[ catch (exception-declaration) {
// code that executes when exception-declaration is thrown
// in the try block
}
[catch (exception-declaration) {
// code that handles another exception type
} ] . . . ]
// The following syntax shows a throw expression:
throw [expression]

本想將兩個(gè)特點(diǎn)與不同詳細(xì)介紹一下,但偶然間發(fā)現(xiàn)前輩已經(jīng)總結(jié)了,它博客的地址為 http://blog.csdn.net/lingqinghua/archive/2005/12/21/558182.aspx

所以SEH與C++異常的不同我就不介紹了,感興趣的可以直接查看他的博客。

現(xiàn)在我們看SEH的過(guò)濾表示式,這個(gè)表達(dá)式可以是常量,條件運(yùn)算符,逗號(hào)表達(dá)式或者其他的函數(shù)。但其結(jié)果必須為0,1,-1這三個(gè)值。其中EXCEPTION_CONTIONUE_SERARCH的值為0,表示本保護(hù)塊不處理該異常,讓系統(tǒng)尋找其他異常處理塊。EXCEPTION_CONTINUE_EXECUTION的值為1,表式已經(jīng)處理了該異常,讓程序返回到異常發(fā)生點(diǎn),繼續(xù)執(zhí)行。這種情況是如果該異常沒(méi)有清除,可能還會(huì)發(fā)生異常。該過(guò)程存在很大的風(fēng)險(xiǎn),因?yàn)閷?duì)于實(shí)際問(wèn)題,很難找到完美的異常解決方案,一旦返回異常點(diǎn)繼續(xù)執(zhí)行,再次發(fā)生異常,因此VC編譯器不準(zhǔn)返回EXCEPTION_CONTINUE_EXECUTION。如果強(qiáng)行返回,將會(huì)導(dǎo)致EXECPTION_NONCONTINUABLE_EXCEPTION異常。EXCEPTION_EXECUTE_HANDLER的值為-1。它的含義是這是本保護(hù)塊預(yù)計(jì)到的異常,當(dāng)發(fā)生該異常后,會(huì)執(zhí)行本塊的異常代碼,執(zhí)行完成后會(huì)繼續(xù)向下執(zhí)行。所以可以在異常處理塊中進(jìn)行記錄異常的一些信息,包括寄存器的信息。

下面我們看VEH(向量化結(jié)構(gòu)處理)

VEH的基本思想是通過(guò)注冊(cè)回調(diào)函數(shù)的方式來(lái)接收和處理異常。回調(diào)函數(shù)的原型為L(zhǎng)ONG CALLBACK VectoredHandler ( PEXCEPTION_POINTERS ExceptionInfo );

對(duì)應(yīng)的有兩個(gè)windows API函數(shù)AddVectoredExceptionHandler(ULONG FirstHandler, PVECTORD_EXCEPTION_HANDLER vectoredHandler)和RemoveVectoredExceptionHandler分別用來(lái)注冊(cè)和注銷回調(diào)函數(shù)。參數(shù)FirstHandler用來(lái)指定該回調(diào)函數(shù)的調(diào)用順序, 為0表示希望最后被調(diào)用,為1表示希望最先被調(diào)用。如果注冊(cè)多個(gè)回調(diào)函數(shù),而且FirstHandler都為非零值,那么最后注冊(cè)的會(huì)最先被調(diào)用。

VEH的示例可以參考《軟件調(diào)試》的304頁(yè)。

最后總結(jié)一下VEH與SEH的區(qū)別。

1. SEH既可以用在用戶態(tài)的代碼中,也可以用在內(nèi)核態(tài)的代碼中。但VEH只能用在用戶態(tài)的代碼中。VEH需要在windows XP以上的版本中使用

2. 如果同時(shí)注冊(cè)了VEH和SEH,那么VEH優(yōu)先處理

3. SEH的注冊(cè)信息是以固定的結(jié)構(gòu)存儲(chǔ)在線程棧中的, VEH的注冊(cè)信息是存儲(chǔ)在進(jìn)程的內(nèi)存堆中的。這讓我想到了一個(gè)問(wèn)題,能夠在進(jìn)程的內(nèi)存中手動(dòng)添加VEH信息,當(dāng)有異常發(fā)生時(shí)就會(huì)執(zhí)行VEH的代碼,這是不是可以破壞一些程序。純屬異想天開(kāi),望高人指點(diǎn)!

4. VEH對(duì)整個(gè)進(jìn)程都有效,而SEH是動(dòng)態(tài)建立在函數(shù)的棧幀上的,會(huì)隨著函數(shù)的返回而被注銷。

5. SEH是依賴編譯器編譯時(shí)生成的數(shù)據(jù)結(jié)構(gòu)和代碼。而VEH的注冊(cè)和注銷都是通過(guò)系統(tǒng)的API顯式完成的,靈活~

謝謝,大部分都是參考的《軟件調(diào)試》,僅一點(diǎn)點(diǎn)心得,希望對(duì)不是很了解的人有些幫助!

VC中的異常處理


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 色综色天天综合网 | 青娱乐伊人 | av在线大全 | 国产熟妇另类久久久久XYZ | 亚洲欧美日韩精品中文乱码 | 亚洲日韩中文字幕一区 | 四虎免费在线视频 | 波多野结衣三级在线观看 | 日产国产欧美视频一区精品 | 日韩伦理一区二区三区 | 成年网站在线看 | 国产精品久久久久久久免费大片 | 国产成人一区二区三区 | 亚洲资源在线视频 | 狠狠干网 | 色六月婷婷 | 日韩大片在线永久观看视频网站免费 | 成人小视频在线观看免费 | 自拍偷拍亚洲欧美 | 精品国产第一国产综合精品 | 欧美亚洲一区二区三区在线 | 欧美日韩国产在线 | 日本韩国三级在线 | 亚洲精品久久久 | 四虎影院最新网站 | 99热官网| 国产成人黄网址在线视频 | 欧美日韩三级在线观看 | 成人99 | 日本一本久道 | 久久新网址 | 欧美一级一片 | 日日久| 不卡视频一区二区 | 久久久久国产一区二区三区 | 国产99页| 免费能直接在线观看黄的视频 | 成人做爰 | 青青草国产 | 91青青青青青爽在线 | 成年人免费网站在线观看 |