日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

窥探try ... catch与__try ... __except的区别

發布時間:2025/7/14 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 窥探try ... catch与__try ... __except的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

VC中的這兩個東西肯定誰都用過, 不過它們之間有什么區別, 正好有時間研究了一下, 如果有錯誤歡迎拍磚.
基于VC2005, 32位XP 平臺測試通過. 估計對于其他版本的VC和操作系統是不通用的.

1. try ... catch

這個是C++語言定義的, 每個C++都有對其的不同的實現. 使用也很簡單. 比如我們有一個函數, 讀入年齡. 如果<=0 或者 >=100, 拋出異常:

int readAge() {
?? int age = 讀入年齡;
?? if (age <=0 || age >= 100) {
????? throw AgeException(age);
?? }
?? return age;
}

其中 AgeException 的定義為

class AgeException {
?? public:
?? int errorAge;
?? AgeException(int age) {
????? errorAge = age;
?? }
};

在使用的時候也比較簡單,

try {
?? int i = readAge();
?? printf("Age inputed is %d", i);
} catch (AgeException e) {
?? printf("error. Age inputed = %d and is not valid.", e.errorAge);
}

2. __try ... __except

這個是VC自己定義的不是C++的關鍵字. VC在編譯__try ... __except的時候, 會按照Windows SEH(結構化異常)處理的規則, 把異常處理部分加入到當前線程的異常處理鏈中. 這部分不詳細寫了, SEH處理在網上的文章一搜一大把.

3. try...catch 與 __try ... __except 使用上的區別

對于上面的AgeException, 我們也可以使用__try... __except 來處理:

__try {
?? int i = readAge();
?? printf("Age inputed is %d", i);
} __except (EXCEPTION_EXECUTE_HANDLER) {
?? printf("Age is not correct.");
}

但是, 對于__try ... __except 能夠處理的異常(比如下面的代碼), C++異常處理try .. catch 不能夠捕獲(Catch段不能執行):

try {
?? int *p = NULL;
?? *p = 0;
} catch (...) {
?? printf("Exception occured.");
}

注: 這里其實和編譯器有關, VC2005由/EH加上參數來控制, 詳情參見http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80).aspx . 這里討論的是默認的情況, 不處理的時候.

這是為什么呢. 仔細看了下, 當我們在程序里面throw出來一個異常的時候, 調試器(比如VC, WinDBG)會記錄下面一個事件:

First-chance exception at 0x7c812afb (kernel32.dll) in trycatch.exe:?Microsoft C++ exception: AgeException at memory location 0x0012fc98..

也就是說, 在VC中, throw出來的都是Microsoft C++ exception. 只有這種Exception才能被try...catch捕獲. 同樣, 用WinDBG裝載上面的程序

__try {
?? int i = readAge();
?? printf("Age inputed is %d", i);
} __except (EXCEPTION_EXECUTE_HANDLER) {
?? printf("Age is not correct.");
}

會發現, 出現的異常為C++ exception, 異常代碼為0xe06d7363:

也就是說, 在C++中throw出來的異常是一種特殊的類型的異常, 是微軟專門為VC++實現的,異常代碼為0xe06d7363. (有意思的是ASCII碼為0x6d, 0x73, 0x63的字符為msc)

到這里我們基本可以得出一個結論, try...catch和__try...__except其實從本質上來說是一回事, 他們從根源上來說都是用到了Windows的SEH處理機制. 不同點在于:

-) try...catch 只處理異常代碼為0xe06d7363的C++ exception, 不會理會其他的;
-) try...catch 對于編譯器來說做了一些額外的工作, 但是最終的實現是和__try...__except都要歸結于SEH
-) try...catch 多了一些額外的傳遞具體的異常信息的部分(catch的是何種異常. 不像是__try...__except, 需要用ExceptionCode去判斷)

想到這, 想到了下面一個問題, 就是VC++編譯器是如何知道catch的異常信息的呢? 換句話說, 對于下面的代碼, 我們知道出現了異常, 但是怎么得到異常的信息的呢?

__try {
?? int i = readAge();
?? printf("Age inputed is %d", i);
} __except (EXCEPTION_EXECUTE_HANDLER) {
?? printf("Age is not correct.");?//如何知道readAge中throw出來的AgeException?
}

為了調試方便, 把異常類和拋出異常的代碼修改一下, 在創建異常的時候傳遞錯誤的age和一條消息

class AgeException {
public:
?? int errorAge;
?? char *p;
?? AgeException(int age, char* msg) {
????? errorAge = age;
????? p = msg;
?? }
};

int readAge() {
?? int age = 123; //
?? if (age <=0 || age >= 100) {
????? throw AgeException(age, "Age is outof range.");
?? }
?? return age;
}

用WinDBG裝入, 運行, 出現了C++異常后, 使用.exr -1?命令查看最近出現的異常:


可以看出, 這個異常為前面討論的C++異常(0xe06d7363類型), 帶有3個參數, 每個參數, 參數分別為0x19930520, 0x0012fca4, 0x00417bc8. 因為我沒有找到C++異常中參數的含義, 只能猜了(哪位如果知道請賜教).

考慮到拋出異常的代碼拋出的異常類型為AgeException, 那么很自然想到拋出的異常作為一個指針存儲在參數中. 因為沒有資料, 只能挨個試驗了. 使用命令dt trycatch!AgeException 地址, 來把trycatch模塊(編譯出的程序名是trycatch.exe)中地址的內容按照類AgeException顯示出來:



果然, 第一個參數0x19930520里面是不是我們想要的; 當輸入第二個參數的時候, 該地址中的內容和預料的一致, 是我們拋出的異常中的內容. 這樣驗證了猜想. try...catch的工作流程為:

-) 編譯器在編譯try...catch的時候, 也是利用Windows的SEH, 只不過僅僅針對C++異常(0xe06d7363類型)進行處理;
-) 拋出異常的時候(throw), 把生成的異常類的實例地址, 保存在異常信息的第二個參數中
-) catch異常的時候, 從異常信息第2個參數中讀出地址, 并轉化為異常類的實例, 供程序使用.

要使用__try...__except模擬上述的過程, 程序可以改為:

__try {
?? int i = readAge();
?? printf("Age inputed is %d", i);
} __except (extract(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {
?? printf("Exception happene.");
}

void extract(LPEXCEPTION_POINTERS p) {
?? int d = p->ExceptionRecord->NumberParameters; //參數數目, 這里沒用到
?? unsigned int * ex = (unsigned int *) p->ExceptionRecord->ExceptionInformation[1];?//第二個參數
?? AgeException * e = (AgeException *) ex;?//轉換,得到異常類的實例
?? printf("==> %d \n", e->errorAge);?//異常的信息可以知道了.
??? printf("==> %s \n", e->p);?//異常的信息可以知道了.
}

運行, 和預期的結果是一致的.

最后可以得到結論(不知道這樣說是否完全正確) :

try...catch是編譯器對__try ... __except的一個包裝; 該包裝僅處理C++異常類型, 但是提供了比較方便的方法來傳遞拋出的異常信息, 這樣程序員能夠比較方便的處理異常, 而不用想上面的例子那樣要手工去異常信息中去取.

轉載于:https://www.cnblogs.com/zhangdongsheng/p/3857509.html

總結

以上是生活随笔為你收集整理的窥探try ... catch与__try ... __except的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产在线欧美在线 | 极品人妻videosss人妻 | 国产欧美精品一区二区色综合 | 黑人干亚洲 | 思思在线视频 | 精品免费囯产一区二区三区 | 在线观看欧美精品 | 亚洲国产精品女人久久久 | 日韩精品在线观看视频 | 人人妻人人爽一区二区三区 | 欧美人体一区二区三区 | 久久久久一区二区三区四区 | jizz教师| 午夜精品在线免费观看 | 成人高清视频在线观看 | 一区二区三区国 | 尤物一区二区 | 最近的中文字幕 | 色婷婷亚洲 | 国产成人免费av一区二区午夜 | 一色综合 | 亚洲最大看欧美片网站 | 亚洲黄色免费在线观看 | 最新中文字幕在线视频 | 公肉吊粗大爽色翁浪妇视频 | 国产精品扒开腿做爽爽爽男男 | 丰满少妇被猛烈进入无码 | 久久久午夜精品福利内容 | 国产成人无码精品久在线观看 | 嫩草在线视频 | 午夜福利电影一区二区 | 最新超碰在线 | 亚洲精品一卡二卡 | 一级特黄色大片 | 天天操天天射天天舔 | 好吊视频一区二区三区四区 | 福利视频在线免费观看 | 国产黄色美女视频 | 看黄色网址 | 欧美影院在线 | 午夜插插插 | 亚洲综合大片69999 | 国产成人片 | 国产欧美久久久久久 | 亚洲午夜精品一区二区三区他趣 | 四虎永久在线精品免费网址 | 日韩精品高清视频 | 可以免费观看av的网站 | 久久夜夜操| 日韩精品 欧美 | 国产ts在线视频 | 欧洲一区二区三区四区 | 久久久无码18禁高潮喷水 | 日韩有码在线播放 | 6080电视影片在线观看 | 日本一本二本三区免费 | 琪琪秋霞午夜被窝电影网 | 老司机深夜福利网站 | 青青草97国产精品麻豆 | 91porny丨首页入口在线 | 女同爱爱视频 | 91久久精品一区二区 | 久久精品免费av | 性久久久久久久久 | 亚洲国产精品成人va在线观看 | 国产精品视频www | 久久久丁香| 日本性爱视频在线观看 | 九九三级| 日韩视频在线一区 | 午夜美女视频 | 妺妺窝人体色777777 | 亚洲欧美国产一区二区 | 成人黄色大片在线观看 | 69er小视频 | 精品国产露脸精彩对白 | 91麻豆成人 | 日本黄色网页 | 西欧free性满足hd老熟妇 | 在线日韩一区二区 | 精品人妻一区二区三区久久夜夜嗨 | 在线日韩精品视频 | 国产资源在线观看 | 香蕉久久夜色精品国产使用方法 | 亚洲人交配视频 | 久久神马影院 | 精品不卡一区二区 | 天天操人人干 | jizz教师 | 免费日韩在线视频 | 亚洲Av无码成人精品区伊人 | 麻豆国产在线视频 | 中文在线播放 | 欧美变态口味重另类在线视频 | 97视频一区二区三区 | 欲色视频| 免费黄色av | 免费黄网在线观看 | 中文字幕中文在线 |