这一节东西比较少,本应该归并在上一节里,但是昨天太晚了。就先把那些东西分为上了。这节里面就一个问题,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 s的R 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 R或E 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的吧,结果是直接崩溃了。

Windows核心编程 第25章 未处理异常和C ++异常(下)的更多相关文章

  1. windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题

    // 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ...

  2. windows核心编程 第5章job lab示例程序 解决小技巧

    看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里”         用process explorer程序查看 ...

  3. windows核心编程---第七章 用户模式下的线程同步

    用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...

  4. Windows核心编程 第十一章 线程池的使用

    第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...

  5. Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)

    7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...

  6. Windows核心编程 第六章 线程基础知识 (上)

    第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ...

  7. Windows核心编程 第四章 进程(上)

    第4章 进 程     本章介绍系统如何管理所有正在运行的应用程序.首先讲述什么是进程,以及系统如何创建进程内核对象,以便管理每个进程.然后将说明如何使用相关的内核对象来对进程进行操作.接着,要介绍进 ...

  8. Windows核心编程 第三章 内核对象

    第3章内核对象 在介绍Windows API的时候,首先要讲述内核对象以及它们的句柄.本章将要介绍一些比较抽象的概念,在此并不讨论某个特定内核对象的特性,相反只是介绍适用于所有内核对象的特性. 首先介 ...

  9. windows核心编程---第五章 线程的基础

    与前面介绍的进程一样,线程也有两部分组成.一个是线程内核对象.它是一个数据结构,操作系统用它来管理线程以及用它来存储线程的一些统计信息.另一个是线程栈,用于维护线程执行时所需的所有函数参数和局部变量. ...

随机推荐

  1. SpringMVC执行流程及源码分析

    SpringMVC流程及源码分析 前言 ​ 学了一遍SpringMVC以后,想着做一个总结,复习一下.复习写下面的总结的时候才发现,其实自己学的并不彻底.牢固.也没有学全,视频跟书本是要结合起来一起, ...

  2. Java 学习阶段性感想

    阶段性感想·操千曲而后晓声 回顾 从2月17日 到 今天 4月19日,我算是暂时完成了Java入门的学习了. 从基本语法到面向对象,从常见API到字符串集合,从文件处理到多线程,我学到了很多,很多很多 ...

  3. Hdfs block数据块大小的设置规则

    1.概述 hadoop集群中文件的存储都是以块的形式存储在hdfs中. 2.默认值 从2.7.3版本开始block size的默认大小为128M,之前版本的默认值是64M. 3.如何修改block块的 ...

  4. Mardown语法

    1.什么是Markdown Mardown是一种文本标记语言,使用它,能让我们更加专注于内容的输出,而不是排版样式. 我们平常使用的.txt文档书写的文字是没有样式的,使用Markdown语法就可以给 ...

  5. 文本相似性计算--MinHash和LSH算法

    给定N个集合,从中找到相似的集合对,如何实现呢?直观的方法是比较任意两个集合.那么可以十分精确的找到每一对相似的集合,但是时间复杂度是O(n2).此外,假如,N个集合中只有少数几对集合相似,绝大多数集 ...

  6. vue 项目集成 husky+commitlint+stylelint

    最近刚换了新工作,这两天也没有业务上的需求,做了一些前端工程化方面的东西.要在现有的项目中集成 husky+commitlint+stylelint,也不能对现有代码产生影响. 使用 lint 的目的 ...

  7. Java学习之路 -- Java怎么学?

    @ 目录 java基础怎么学? 学完基础学什么? 几个常用框架学完学什么? MQ JVM的知识跑不掉 微服务等等 其他 数据结构和算法 java基础怎么学? 当时,作为懵懂的小白,大一学习了c和c++ ...

  8. java例题_25 判断是否为回文数!

    1 /*25 [程序 25 求回文数] 2 题目:一个 5 位数,判断它是不是回文数.即 12321 是回文数,个位与万位相同,十位与千位相同. 3 */ 4 5 /*分析 6 * 先用%和/将5个数 ...

  9. vue全局错误捕获

    1.errorHandler Vue全局配置 errorHandler可以进行全局错误收集,捕获全局错误抛出,避免前端页面挂掉   export default function errorHandl ...

  10. vue中的.sync修饰符用法

    在项目中接触到父组件传值给子组件的时候,想在子组件改变父组件传的值.(比如用于弹窗关闭) 但是正常来说,vue2是不允许子组件直接改父组件传进去的值的. 所以我们需要在子组件内定义自定义事件,通知父组 ...