Windows核心编程 第25章 未处理异常和C ++异常(下)

来源:互联网 发布:mac pro怎么关闭qq 编辑:程序博客网 时间:2024/05/08 22:01

    这一节东西比较少,本应该归并在上一节里,但是昨天太晚了。就先把那些东西分为上了。这节里面就一个问题,C++异常与结构性异常的对比(try__try的区别)

C++异常与结构性异常的对比

    S E H是可用于任何编程语言的操作系统设施,而异常处理只能用于编写

C + +代码。如果你在编写C + +程序,你应该使用C + +异常处理而不是结构化异常处理。理由是C + +异常处理是语言的一部分,编译器知道 C + +类对象是什么。也就是说编译器能够自动生成代码来调用C + +对象析构函数,保证对象的清除。

    但是也应该知道,Microsoft Visual C++编译器已经利用操作系统的结构化异常处理实现了C + +异常处理。所以当你建立一个 C++ try块时,编译器就生成一个 S E H_ _t r y块。一个C + +c a t c h测试变成一个S E H异常过滤器,并且c a t c h中的代码变成S E H_ _e x c e p t块中的代码。实际上,当你写一条C++ throw语句时,编译器就生成一个对Wi n d o w sR a i s e E x c e p t i o n函数的调用。用于t h r o w语句的变量传递给R a i s e E x c e p t i o n作为附加的参数。

    下面的代码段可以使上面的叙述更清楚一些。左边的函数使用 C + +异常处理,右边的函数说明了C + +编译器如何生成等价的结构化异常处理。


    你可能注意到上面代码中一些有趣的细节。首先,函数 R a i s e E x c e p t i o n的调用使用了异常代码0 x E 0 6 D 7 3 6 3。这是由Visual C++的开发人员选择的软件异常代码,在引发C + +异常时使用。事实上你可以验证这一点,方法是打开调试程序的 E x c e p t i o n s对话框,滚动到异常列表的底部,见图2 5 - 1 5

    当引发了C + +异常时,总要使用E X C E P T I O N _ N O N C O N T I N U E A B L E标志。C + +异常不能被重新执行。对于诊断C + +异常的过滤器,如果返回E X C E P T I O N _ C O N T I N U E _ E X E C U T I O N,那将是个错误。实际上,我们看一看上面程序段右边函数中的 _ _ e x c e p t过滤器,就会发现它只能计算成E X C E P T I O N _ E X E C U T E _ H A N D L E RE X C E P T I O N _ C O N T I N U E _ S E A R C H

    传递到R a i s e E x c e p t i o n的其余参数是用来作为一种机制,用于实际引发指定的变量。被引发的变量信息是如何传递到 R a i s e E x c e p t i o n的,这一点没有公开。但不难想像编译器的开发人员可以实现这一点。


    最后要指出的是_ _ e x c e p t过滤器。这个过滤器的用途是将t h r o w变量的数据类型同用于C + +c a t c h语句的变量类型相比较。如果数据类型相同,过滤器返回 E X C E P T I O N _ E X E C U T E _H A N D L E R,导致c a t c h块(_ _ e x c e p t块)中的语句执行。如果数据类型不同,过滤器返回E X C E P T I O N _ C O N T N U E _ S E A R C H,导致c a t c h过滤器上溯要计算的调用树。

正常情况下,C + +异常处理不能使程序从硬件异常中恢复,硬件违规就是存取违规或零作除数这种异常。但微软已经对其编译器增加了这种支持能力。例如,下面的代码可以防止进程不正常地结束:(VS默认是Release可以,Debug的话还是会掉相关处理函数,然后弹异常窗)


    同时catch里面还可以细分,就是判断异常类型然后做相应处理:Visuad C++有一种机制可以实现这一点。你需要做的是建立你自己的C + +类,在代码中用来标识结构性异常。这里是一个例子:

    在每个线程的进入点函数里,调用静态成员函数 M a p S E t o C E。这个函数调用C运行时函数_ s e t _ s e _ t r a n s l a t o r,并传递 C S E类的 Tr a n s l a t e S E t o C E函数的地址作为参数。通过调用_ s e t _ s e _ t r a n s l a t o r,告诉C + +运行时系统,在结构性异常发生时调用 Tr a n s l a t e S E t o C E函数。这个函数构造一个C S E类对象并初始化两个数据成员以包含有关异常的 C P U独立和C P U依赖的信息。在构造了C S E对象之后,它就被引发,如同任何正常的变量可被引发一样。现在你的 C + +代码可以通过捕获一个这类的变量来处理结构性异常。

下面是如何捕获这个C + +对象的例子。

 

额...讲道理是应该先输出个111然后输出222的吧,结果是直接崩溃了。

0 0
原创粉丝点击