• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            yehao's Blog

            C++及Windows異常處理(try,catch; __try,__finally; __try, __except)

            題目:

             int* p = 0x00000000; // pointer to NULL
             puts( "hello ");
             __try{
             puts( "in try ");
             __try{
             puts( "in try ");
             *p = 13; // causes an access violation exception;
             }__finally{
             puts( "in finally ");
             }
             }__except(puts( "in filter "), 1){
             puts( "in except ");
             }
             puts( "world ");
             /*
             hello
             in try
             in try
             in filter
             in finally
             in except
             world
             */

            上面的題目,我把答案列了出來。

            常用C++的朋友,應(yīng)該沒見過__try這種形式的語句,下面我把try,catch; __try,__finally; __try, __except這三對(duì)異常處理使用標(biāo)示逐一說明

             

            本文參考了如下博文:

            http://www.cnblogs.com/wenziqi/archive/2010/08/26/1809074.html

            http://blog.csdn.net/lvwenshuai/article/details/6163342

            http://topic.csdn.net/t/20030527/10/1838724.html

            http://zhidao.baidu.com/question/183400727.html

             

            • C++ 異常處理:try,catch
            try { // 可能出錯(cuò)的語句 // 如果有錯(cuò),就—— throw ... // 初始化一個(gè)異常對(duì)象(exception object) } catch( 類型名 [形參名] ) /* 異常說明符(exception specifier)*/ { } catch( 類型名 [形參名] ) { }

            C++的異常處理很簡單,就是如上的三個(gè)關(guān)鍵字,注意C++中throw,catch之后沒有Java等語言中的finally。

            Q: 為何C++不提供“finally”結(jié)構(gòu)? 
            A: 因?yàn)镃++提供了另一種機(jī)制,完全可以取代finally,而且這種機(jī)制幾乎總要比finally工作得更好:就是——“分配資源即初始化”。(見《The C++ Programming Language》14.4節(jié))基本的想法是,用一個(gè)局部對(duì)象來封裝一個(gè)資源,這樣一來局部對(duì)象的析構(gòu)函數(shù)就可以自動(dòng)釋放資源。這樣,程序員就不會(huì)“忘記釋放資源”了。 [譯注:因?yàn)镃++的對(duì)象“生命周期”機(jī)制替他記住了 :O) ] 下面是一個(gè)例子:

            class File_handle {
             FILE* p;
             public:
             File_handle(const char* n, const char* a)
             { p = fopen(n,a); if (p==0) throw Open_error(errno); }
             File_handle(FILE* pp)
             { p = pp; if (p==0) throw Open_error(errno); }
             
             ~File_handle() { fclose(p); }
             
             operator FILE*() { return p; }
             
             // ...
             };
             
             void f(const char* fn)
             {
             File_handle f(fn,"rw"); // open fn for reading and writing
             // use file through f
             }

            在一個(gè)系統(tǒng)中,每一樣資源都需要一個(gè)“資源局柄”對(duì)象,但我們不必為每一個(gè)資源都寫一個(gè)“finally”語句。在實(shí)作的系統(tǒng)中,資源的獲取和釋放的次數(shù)遠(yuǎn)遠(yuǎn)多于資源的種類,所以“資源分配即初始化”機(jī)制產(chǎn)生的代碼要比“finally”機(jī)制少。

             

            好了,接下來,看另外兩組異常模型機(jī)制,它們是Windows系列操作系統(tǒng)平臺(tái)上提供的SEH模型,也就是說在C++中調(diào)用的時(shí)候,其實(shí)是調(diào)用Windows的API

            SEH,又稱結(jié)構(gòu)化異常處理.是設(shè)計(jì)Windows操作系統(tǒng)時(shí)提出一個(gè)種處理異常的方法。

            • __try, __except

            這組異常處理機(jī)制和C++的很相像,只是關(guān)鍵字是except而不是catch

            catch 和 except 的一點(diǎn)不同: catch關(guān)鍵字后面往往好像接受一個(gè)函數(shù)參數(shù)一樣,可以是各種類型的異常數(shù)據(jù)對(duì)象;但是__except關(guān)鍵字則不同,它后面跟的卻是一個(gè)表達(dá)式(可以是各種類型的表達(dá)式)

            下面是一個(gè)例子:

            void main()
            {
             puts("hello");
             // 定義受監(jiān)控的代碼模塊
             __try
             {
             puts("in try");
             }
             //定義異常處理模塊
             __except(1)
             {
             puts("in except");
             }
             puts("world");
            }

            1. 受監(jiān)控的代碼模塊被執(zhí)行(也即__try定義的模塊代碼); 
            2. 如果上面的代碼執(zhí)行過程中,沒有出現(xiàn)異常的話,那么控制流將轉(zhuǎn)入到__except子句之后的代碼模塊中; 
            3. 否則,如果出現(xiàn)異常的話,那么控制流將進(jìn)入到__except后面的表達(dá)式中,也即首先計(jì)算這個(gè)表達(dá)式的值,之后再根據(jù)這個(gè)值,來決定做出相應(yīng)的處理。

            EXCEPTION_CONTINUE_EXECUTION (–1) 異常被忽略,控制流將在異常出現(xiàn)的點(diǎn)之后,繼續(xù)恢復(fù)運(yùn)行。 
            EXCEPTION_CONTINUE_SEARCH (0) 異常不被識(shí)別,也即當(dāng)前的這個(gè)__except模塊不是這個(gè)異常錯(cuò)誤所對(duì)應(yīng)的正確的異常處理模塊。系統(tǒng)將繼續(xù)到上一層的try-except域中繼續(xù)查找一個(gè)恰當(dāng)?shù)腳_except模塊。 
            EXCEPTION_EXECUTE_HANDLER (1) 異常已經(jīng)被識(shí)別,也即當(dāng)前的這個(gè)異常錯(cuò)誤,系統(tǒng)已經(jīng)找到了并能夠確認(rèn),這個(gè)__except模塊就是正確的異常處理模塊。控制流將進(jìn)入到__except模塊中。

            小結(jié):

            (1) C++異常模型用try-catch語法定義,而SEH異常模型則用try-except語法;

            (2) 與C++異常模型相似,try-except也支持多層的try-except嵌套。

            (3) 與C++異常模型不同的是,try-except模型中,一個(gè)try塊只能是有一個(gè)except塊;而C++異常模型中,一個(gè)try塊可以有多個(gè)catch塊。

            (4) 與C++異常模型相似,try-except模型中,查找搜索異常模塊的規(guī)則也是逐級(jí)向上進(jìn)行的。但是稍有區(qū)別的是,C++異常模型是按照異常對(duì)象的類型來進(jìn)行匹配查找的;而try-except模型則不同,它通過一個(gè)表達(dá)式的值來進(jìn)行判斷。如果表達(dá)式的值為1(EXCEPTION_EXECUTE_HANDLER),表示找到了異常處理模塊;如果值為0(EXCEPTION_CONTINUE_SEARCH),表示繼續(xù)向上一層的try-except域中繼續(xù)查找其它可能匹配的異常處理模塊;如果值為-1(EXCEPTION_CONTINUE_EXECUTION),表示忽略這個(gè)異常,注意這個(gè)值一般很少用,因?yàn)樗苋菀讓?dǎo)致程序難以預(yù)測的結(jié)果,例如,死循環(huán),甚至導(dǎo)致程序的崩潰等。

            (5) __except關(guān)鍵字后面跟的表達(dá)式,它可以是各種類型的表達(dá)式,例如,它可以是一個(gè)函數(shù)調(diào)用,或是一個(gè)條件表達(dá)式,或是一個(gè)逗號(hào)表達(dá)式,或干脆就是一個(gè)整型常量等等。最常用的是一個(gè)函數(shù)表達(dá)式,并且通過利用GetExceptionCode()或GetExceptionInformation ()函數(shù)來獲取當(dāng)前的異常錯(cuò)誤信息,便于程序員有效控制異常錯(cuò)誤的分類處理。

            (6) SEH異常處理模型中,異常被劃分為兩大類:系統(tǒng)異常和軟件異常。其中軟件異常通過RaiseException()函數(shù)拋出。RaiseException()函數(shù)的作用類似于C++異常模型中的throw語句。

            詳細(xì)的請參看:http://www.cnblogs.com/wenziqi/archive/2010/08/26/1809074.html

             

            • __try, __finally

            try-finally語句的語法與try-except很類似,稍有不同的是,__finally后面沒有一個(gè)表達(dá)式,這是因?yàn)閠ry- finally語句的作用不是用于異常處理,所以它不需要一個(gè)表達(dá)式來判斷當(dāng)前異常錯(cuò)誤的種類。另外,與try-except語句類似,try- finally也可以是多層嵌套的,并且一個(gè)函數(shù)內(nèi)可以有多個(gè)try-finally語句,不管它是嵌套的,或是平行的。當(dāng)然,try-finally多層嵌套也可以是跨函數(shù)的。

            最關(guān)鍵的一點(diǎn): “不管在何種情況下,在離開當(dāng)前的作用域時(shí),finally塊區(qū)域內(nèi)的代碼都將會(huì)被執(zhí)行到”

            void tmain()
            {
             puts("hello");
             __try
             {
             puts("__try塊中");
             
             // 注意,下面return語句直接讓函數(shù)返回了
             return;
             }
             __finally
             {
             puts("__finally塊中");
             }
             
             puts("world");

            上面的程序運(yùn)行結(jié)果如下: 
            hello 
            __try塊中 
            __finally塊中 
            Press any key to continue

             

            小結(jié):

            __finally塊被執(zhí)行的流程時(shí),無外乎三種情況。

            第一種就是順序執(zhí)行到__finally塊區(qū)域內(nèi)的代碼,這種情況很簡單,容易理解;

            第二種就是goto語句或return語句引發(fā)的程序控制流離開當(dāng)前__try塊作用域時(shí),系統(tǒng)自動(dòng)完成對(duì)__finally塊代碼的調(diào)用;

            第三種就是由于在__try塊中出現(xiàn)異常時(shí),導(dǎo)致程序控制流離開當(dāng)前__try塊作用域,這種情況下也是由系統(tǒng)自動(dòng)完成對(duì)__finally塊的調(diào)用。

            無論是第 2種,還是第3種情況,毫無疑問,它們都會(huì)引起很大的系統(tǒng)開銷,編譯器在編譯此類程序代碼時(shí),它會(huì)為這兩種情況準(zhǔn)備很多的額外代碼。

            一般第2種情況,被稱為“局部展開(LocalUnwinding)”;第3種情況,被稱為“全局展開(GlobalUnwinding)”。在后面闡述SEH實(shí)現(xiàn)的時(shí)候會(huì)詳細(xì)分析到這一點(diǎn)。

            第3種情況,也即由于出現(xiàn)異常而導(dǎo)致的“全局展開”,對(duì)于程序員而言,這也許是無法避免的,因?yàn)槟阍诶卯惓L幚頇C(jī)制提高程序可靠健壯性的同時(shí),不可避免的會(huì)引起性能上其它的一些開銷。呵呵!這世界其實(shí)也算瞞公平的,有得必有失。


            到此,本文開頭的那段代碼的結(jié)果就沒有任何懸念了,O(∩_∩)O哈哈~,每天進(jìn)步一點(diǎn)點(diǎn)~~~~~~~~

            轉(zhuǎn)自:http://shijuanfeng.blogbus.com/logs/178616871.html

            posted on 2012-02-07 14:32 厚積薄發(fā) 閱讀(12548) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C/C++

            導(dǎo)航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆分類

            文章分類

            文章檔案

            搜索

            最新評(píng)論

            亚洲国产成人久久一区久久| av午夜福利一片免费看久久| 国产无套内射久久久国产| 91精品免费久久久久久久久| 久久亚洲国产精品123区| 日产精品久久久一区二区| 国产高清美女一级a毛片久久w| 久久影视综合亚洲| 久久精品中文闷骚内射| 久久亚洲欧洲国产综合| 蜜臀av性久久久久蜜臀aⅴ麻豆| 国产亚洲色婷婷久久99精品91 | 97超级碰碰碰碰久久久久| 理论片午午伦夜理片久久 | 亚洲国产精品高清久久久| 久久久久久a亚洲欧洲aⅴ | 久久久免费精品re6| 狠狠精品干练久久久无码中文字幕| 国产亚洲精品久久久久秋霞 | 国产日产久久高清欧美一区| 久久亚洲精品国产亚洲老地址| 久久被窝电影亚洲爽爽爽| 久久精品人人做人人爽97| 欧美久久天天综合香蕉伊| 99久久99久久精品国产| 久久99国产精品99久久| 日产精品久久久久久久性色| 7777精品久久久大香线蕉| 久久夜色精品国产噜噜亚洲a| 久久久久亚洲AV无码去区首| 成人国内精品久久久久影院VR| av午夜福利一片免费看久久| 久久精品国产亚洲αv忘忧草| 区亚洲欧美一级久久精品亚洲精品成人网久久久久| 国产精品女同久久久久电影院 | 久久国产亚洲精品麻豆| 99久久综合狠狠综合久久止| 精品久久久久久国产91| 狠狠色婷婷综合天天久久丁香 | 欧美色综合久久久久久| 欧美午夜A∨大片久久|