您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 创业/孵化 > C++异常和Windows结构异常的比较
查看文章try...catch与__try...__except2009-09-2411:43VC中的这两个东西肯定谁都用过,不过它们之间有什么区别,正好有时间研究了一下,如果有错误欢迎拍砖.基于VC2005,32位XP平台测试通过.估计对于其他版本的VC和操作系统是不通用的.1.try...catch这个是C++语言定义的,每个C++都有对其的不同的实现.使用也很简单.比如我们有一个函数,读入年龄.如果=0或者=100,抛出异常:intreadAge(){intage=读入年龄;if(age=0||age=100){throwAgeException(age);}returnage;}其中AgeException的定义为classAgeException{public:interrorAge;AgeException(intage){errorAge=age;}};在使用的时候也比较简单,try{inti=readAge();printf(Ageinputedis%d,i);}catch(AgeExceptione){printf(error.Ageinputed=%dandisnotvalid.,e.errorAge);}2.__try...__except这个是VC自己定义的不是C++的关键字.VC在编译__try...__except的时候,会按照WindowsSEH(结构化异常)处理的规则,把异常处理部分加入到当前线程的异常处理链中.这部分不详细写了,SEH处理在网上的文章一搜一大把.3.try...catch与__try...__except使用上的区别对于上面的AgeException,我们也可以使用__try...__except来处理:__try{inti=readAge();printf(Ageinputedis%d,i);}__except(EXCEPTION_EXECUTE_HANDLER){printf(Ageisnotcorrect.);}但是,对于__try...__except能够处理的异常(比如下面的代码),C++异常处理try..catch不能够捕获(Catch段不能执行):try{int*p=NULL;*p=0;}catch(...){printf(Exceptionoccured.);}注:这里其实和编译器有关,VC2005由/EH加上参数来控制,详情参见(VS.80).aspx.这里讨论的是默认的情况,不处理的时候.这是为什么呢.仔细看了下,当我们在程序里面throw出来一个异常的时候,调试器(比如VC,WinDBG)会记录下面一个事件:First-chanceexceptionat0x7c812afb(kernel32.dll)intrycatch.exe:MicrosoftC++exception:AgeExceptionatmemorylocation0x0012fc98..也就是说,在VC中,throw出来的都是MicrosoftC++exception.只有这种Exception才能被try...catch捕获.同样,用WinDBG装载上面的程序__try{inti=readAge();printf(Ageinputedis%d,i);}__except(EXCEPTION_EXECUTE_HANDLER){printf(Ageisnotcorrect.);}会发现,出现的异常为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{inti=readAge();printf(Ageinputedis%d,i);}__except(EXCEPTION_EXECUTE_HANDLER){printf(Ageisnotcorrect.);//如何知道readAge中throw出来的AgeException?}为了调试方便,把异常类和抛出异常的代码修改一下,在创建异常的时候传递错误的age和一条消息classAgeException{public:interrorAge;char*p;AgeException(intage,char*msg){errorAge=age;p=msg;}};intreadAge(){intage=123;//if(age=0||age=100){throwAgeException(age,Ageisoutofrange.);}returnage;}用WinDBG装入,运行,出现了C++异常后,使用.exr-1命令查看最近出现的异常:可以看出,这个异常为前面讨论的C++异常(0xe06d7363类型),带有3个参数,每个参数,参数分别为0x19930520,0x0012fca4,0x00417bc8.因为我没有找到C++异常中参数的含义,只能猜了(哪位如果知道请赐教).考虑到抛出异常的代码抛出的异常类型为AgeException,那么很自然想到抛出的异常作为一个指针存储在参数中.因为没有资料,只能挨个试验了.使用命令dttrycatch!AgeException地址,来把trycatch模块(编译出的程序名是trycatch.exe)中地址的内容按照类AgeException显示出来:果然,第一个参数0x19930520里面是不是我们想要的;当输入第二个参数的时候,该地址中的内容和预料的一致,是我们抛出的异常中的内容.这样验证了猜想.try...catch的工作流程为:-)编译器在编译try...catch的时候,也是利用Windows的SEH,只不过仅仅针对C++异常(0xe06d7363类型)进行处理;-)抛出异常的时候(throw),把生成的异常类的实例地址,保存在异常信息的第二个参数中-)catch异常的时候,从异常信息第2个参数中读出地址,并转化为异常类的实例,供程序使用.要使用__try...__except模拟上述的过程,程序可以改为:__try{inti=readAge();printf(Ageinputedis%d,i);}__except(extract(GetExceptionInformation()),EXCEPTION_EXECUTE_HANDLER){printf(Exceptionhappene.);}voidextract(LPEXCEPTION_POINTERSp){intd=p-ExceptionRecord-NumberParameters;//参数数目,这里没用到unsignedint*ex=(unsignedint*)p-ExceptionRecord-ExceptionInformation[1];//第二个参数AgeException*e=(AgeException*)ex;//转换,得到异常类的实例printf(==%d\n,e-errorAge);//异常的信息可以知道了.printf(==%s\n,e-p);//异常的信息可以知道了.}运行,和预期的结果是一致的.最后可以得到结论(不知道这样说是否完全正确):try...catch是编译器对__try...__except的一个包装;该包装仅处理C++异常类型,但是提供了比较方便的方法来传递抛出的异常信息,这样程序员能够比较方便的处理异常,而不用想上面的例子那样要手工去异常信息中去取.相册留言用户操作[留言][发消息][加为好友]陈明亮ID:cml2030共10649次访问,排名15936,好友18人,关注者16人。陈明亮的文章原创44篇翻译0篇转载12篇评论7篇订阅我的博客[编辑]cml2030的公告因为工作原因,编程语言常常要切换,需要一个博客整理一下基础知识,备忘.技术交流QQ:5862177(注:CSDN)[编辑]文章分类ActiveXASP.NETC#与.NETC/C++语言DelphiVC/MFCWindows编程基础Windows网络编程其它存档2010年12月(6)2010年11月(3)2010年09月(1)2010年08月(4)2010年04月(1)2010年03月(1)2010年02月(2)2009年12月(2)2009年11月(1)2009年07月(2)2009年06月(2)2009年04月(1)2009年03月(1)2008年12月(3)2008年10月(6)2008年09月(1)2008年07月(1)2008年06月(3)2008年03月(15)公告:2011年4月微软MVP申请开始啦!有兴趣的抓紧时间哦![意见反馈][官方博客]C++异常与windows结构化异常处理简单说明收藏一、C++标准异常try{……throwexception-data……}catch(exception-declaration1){……}catch(exception-declaration2){……}try块中的throw会抛出一个数据exception-data,比如一个整数,一个字串,或是其他自定义类型的数据。这时,当前程序中止执行,开始查找catch入口。throw抛出的数据类型与catch入口的exception-declaration数据类型必须匹配,这一点类似函数调用的形参、实参匹配。一个try块可以对应多个catch块,也可以用catch(…)来接收所有可能抛出的数据。强调:必须是在程序代码快中有出现异常时主动抛出异常才会,异常才能截获进入异常处理,也就是说,如果程序中没有throw你加上try块也是没有意义的.二、WindowsSEHSEH(StructuredExceptionHandling),即结构化异常处理,是Microsoft提供的异常处理机制。要了解这个机制,咱先来了解一下__try-__except关键字。1.__try-__except关键字__try{……}__except(exception){……}__try-__except是Microsoft扩展出的C++关键字,__try块中出现错误或异常,一般不再用throw抛出,而是直接产生一个EXCEPTION_POINTERS类型的异常数据,然后开始查找SEH例程入口(调试的情况除外)。首先就会找到与__try块对应的__except块。__except的参数exception与catch的参数作用完全不同,也不类似于函数的参数,它主要是用于控制后面的程序执行,为这几个值之一:EXCEPTION_EXECUTE_HANDLER(1)表示下面执行__except块内及其后面的代码EXCEPTION_CONTINUE_EXECUTION(-1)表示回到抛出异常处继续向下执行EXCEPTION_CONTINUE_SEARCH(0)表示查找下一个异常处理例程入口Micr
本文标题:C++异常和Windows结构异常的比较
链接地址:https://www.777doc.com/doc-2904234 .html