第2 3章 结束处理程序

SEH(结构化异常处理)

使用 S E H的好处就是当你编写程序时,只需要关注程序要完成的任务。

如果在运行时发生什么错误,系统会发现并将发生的问题通知你。利用S E H,你可以完全不用考虑代码里是不是有错误,这样就把主要的工作同错误处理分离开来。这样的分离,可以使你集中精力处理眼前的工作,而将可能发生的错误放在后面处理。

S E H实际包含两个主要功能:结束处理( termination handling)和异常处理( e x c e p t i o nh a n d l i n g)。本章讨论结束处理,下一章讨论异常处理。

注意:不要将结构化异常处理同C + +的异常处理相混淆。C + +异常处理是一种不同形

式的异常处理,其形式是使用C + +关键字c a t c h和t h r o w。最后再区分这两个的区别。

下面是基本调用样子:

- - t r y和- - f i n a l l y关键字用来标出结束处理程序两段代码的轮廓。在上面的代码段中,操作系统和编译程序共同来确保结束处理程序中的 - - f i n a l l y代码块能够被执行,不管保护体( t r y块)是如何退出的。不论你在保护体中使用 r e t u r n,还是g o t o,或者是l o n g j u m p,结束处理程序(f i n a l l y块)都将被调用。

要完成这些事情,编译程序必须生成附加的代码,系统要执行额外的工作。在不同的C P U上,结束处理所需要的步骤也不同。例如,在 A l p h a处理器上,必须执行几百个甚至几千个C P U指令来捕捉t r y块中的过早返回并调用f i n a l l y块。在编写代码时,就应该避免引起结束处理程序的t r y块中的过早退出,因为程序的性能会受到影响。

注意当控制流自然地离开t r y块并进入f i n a l l y块(就像在F u n c e n s t e i n 1中)时,进入f i n a l l y块的系统开销是最小的。在x86 CPU上使用微软的编译程序,当执行离开 try 块进入f i n a l l y块时,只有一个机器指令被执行。

常用举例:

1.

会弹出崩溃框,但是点击关闭后会执行finally代码,但是不会执行第二个messagebox:

2.下面这个函数返回14,自己好好理解下:

3.下面这个,按照书上的意思是返回2,然而是没编译过去(vs2012 C++)

4.书上写了三个函数,同功能,直接截图过来了

(1)

(2)

(3)

5.最终的边界

为了帮助避免在t r y块中使用r e t u r n语句,微软在其C / C + +编译程序中增加了另一个关键字- -l e a v e。这里是F u n c a r m a 4版,它使用了- - l e a v e关键字:

如果直接这样:

那么return导致的进入finally的状态不是流入的,也就是需要很多辅助代码来处理,如果直接使用__leave

那就是类似如下优化:

从而优化了执行时间。

关于f i n a l l y块的说明

已经明确区分了强制执行f i n a l l y块的两种情况:

• 从t r y块进入f i n a l l y块的正常控制流。

• 局部展开:从t r y块的过早退出(g o t o、l o n g j u m p、c o n t i n u e、b r e a k、r e t u r n等)强制控制转移到f i n a l l y块。

第三种情况,全局展开( global unwind),在发生的时候没有明显的标识,我们在本章前面F u n c f u r t e r 1函数中已经见到。在F u n c f u r t e r 1的t r y块中,有一个对F u n c i n a t o r函数的调用。如果F u n c i n a t o r函数引起一个内存访问违规( memory access violation),一个全局展开会使F u n c f u r t e r 1的f i n a l l y块执行。下一章将详细讨论全局展开。

由于以上三种情况中某一种的结果而导致f i n a l l y块中的代码开始执行。为了确定是哪一种情况引起f i n a l l y块执行,可以调用内部函数(或内蕴函数,intrinsic function)Abnormal Te r m i n a t i o n:

BOOL AbnormalTermination();

这个内部函数只在f i n a l l y块中调用,返回一个B o o l e a n值。指出与f i n a l l y块相结合的t r y块是否过早退出。换句话说,如果控制流离开 t r y块并自然进入f i n a l l y块,A b n o r m a l Te r m i n a t i o n将返回FA L S E。如果控制流非正常退出 t r y块 — 通常由于g o t o、r e t u r n、b r e a k或c o n t i n u e语句引起的局部展开,或由于内存访问违规或其他异常引起的全局展开 — 对A b n o r m a l Te r m i n a t i o n的调用将返回T R U E。没有办法区别f i n a l l y块的执行是由于全局展开还是由于局部展开。但这通常不会成为问题,因为可以避免编写执行局部展开的代码。

使用结束处理程序的理由:

• 简化错误处理,因所有的清理工作都在一个位置并且保证被执行。

• 提高程序的可读性。

• 使代码更容易维护。

• 如果使用得当,具有最小的系统开销。

Try和__Try区别:

异常处理

结果是输出两个对话框,没有崩溃界面。

SEH

结果是先输出一个崩溃页面,点击关闭,弹出matk1对话框。

Windows核心编程 第23章 结束处理程序的更多相关文章

  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核心编程 第六章 线程基础知识 (上)

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

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

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

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

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

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

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

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

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

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

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

  9. windows核心编程---第六章 线程的调度

    每个线程都有一个CONTEXT结构,保存在线程内核对象中.大约每隔20ms windows就会查看所有当前存在的线程内核对象.并在可调度的线程内核对象中选择一个,将其保存在CONTEXT结构的值载入c ...

随机推荐

  1. windows基线检测脚本编写指南-powershell版

    前言:   因为工作的原因,要写windows下的基线检查脚本.之前没接触过,在网上找了半天也没找到现成的,无奈只好自己研究,最后还是成功完成了工作. 在我编写之后发现windows下的基线基本就是检 ...

  2. 一文弄懂js的执行上下文与执行上下文栈

    目录 执行上下文与执行上下文栈 变量提升与函数提升 变量提升 函数提升 变量提升与函数提升的优先级 变量提升的一道题目引出var关键字与let关键字各自的特性 执行上下文 全局执行上下文 函数(局部) ...

  3. python-socket和进程线程协程(代码展示)

    socket # 一.socket # TCP服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bin ...

  4. 学习jQuery(1)

    学习jQuery 通过 jQuery,您可以选取(查询,query) HTML 元素,并对它们执行"操作"(actions). jQuery 语法 jQuery 语法是为 HTML ...

  5. Fork/Join 框架

    本文部分摘自<Java 并发编程的艺术> Fork/Join 框架概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是把一个大任务分割成若干个小任务,最终汇总 ...

  6. Android Studio中批量注释 Java代码

    •ctrl+/ 选中需要注释的多行代码,然后按 ctrl + / 实现多行快速注释: 再次按下 ctrl + / 取消注释. •ctrl+shift+/ 选中一行或几行代码,按 ctrl + shif ...

  7. 分享15个实用VSCode插件,快来收藏吧!

    Visual Studio Code 是由微软开发的一款免费.跨平台的文本编辑器.它有卓越的性能和丰富的功能.VSCode 也有一个扩展和主题市场,为了帮助大家挑选出值得下载的插件,我们针对性的收集了 ...

  8. 生产环境中mysql数据库由主从关系切换为主主关系

    目录 一.清除原从数据库数据及主从关系 1.1.关闭主从数据库原有的主从关系 1.2.清除从数据库原有数据 二.将主库上的数据备份到从库 2.1.备份主库数据到从库 2.2.在从库使用tsc.sql文 ...

  9. Redis-AOF日志与RDB快照

    AOF日志与RDB是Reids中两大持久化机制,当服务器或者Reids宕机的时候可以通过这两大机制恢复Redis的数据. 先说说AOF日志吧,在执行一条操作请求时,Redis先将命令在内存中执行,之后 ...

  10. leetcode 783 二叉搜索树节点最小距离

    PS:(感觉这题名字和内容有歧义) 要求得到任意不同节点值之间的最小差值. 本身二叉树是有序的,又找最小差值,其实就是相当于在一个有序数组中找到每相邻两数之间最小差值. 朴素思想: 中序遍历树,把值都 ...