第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. rest-framework routers

    路由器 资源路由可以让你快速声明所有给定的足智多谋的控制器的共同路线.相反,宣布独立的路线索引的......一个足智多谋的路线宣称他们在一个单一的代码行. - Ruby on Rails的文档 一些W ...

  2. WPF 基础 - 在模板中找元素

    1. 在 ControlTemplate 中寻找元素 <Window.Resources> <ControlTemplate x:Key="cTmp"> & ...

  3. golang 三维向量相关操作

    package vector import ( "math" "fmt" )// 三维向量:(x,y,z) type Vector3 struct { X fl ...

  4. FHRP - 网关冗余协议

    通常情况下,在终端设备进入网络前,都会有一个 Router 充当网络,作为第一跳的网络地址.但假设路由器发生故障,此时终端设备就无法再接入互联网. 为了防止这样的问题,一般会再加入一台路由器充当备份. ...

  5. socket 之send和recv原理剖析

    认识TCP socket的发送缓冲区和接收缓冲区 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,相当与内存中的一片空间 send原理剖析 send是不是直接把数据发送给服 ...

  6. 面向对象进阶时,if语句写错位置

    这周blog我也不知道要写什么,因为这章我其实学得有点懵,前面那几天我纠结了好久代码,一直不知道原因错在哪里.后来经过询问老师才知道自己调用错了构造方法,相信也有跟我一样的新手会犯这个错误.我在创建关 ...

  7. dll远线程注入

    原理 核心函数 CreateRemoteThread:让在其他进程中创建一个线程变成可能 核心思想 HANDLE WINAPI CreateRemoteThread( __in HANDLE hPro ...

  8. [BFS]最小转弯问题

    最小转弯问题 Description 给出一张地图,这张地图被分为 n×m(n,m<=100)个方块,任何一个方块不是平地就是高山.平地可以通过,高山则不能.现在你处在地图的(x1,y1)这块平 ...

  9. MySQL提升笔记(1):MySQL逻辑架构

    深入学习MySQL,从概览MySQL逻辑架构开始. 首先来看一下MySQL的逻辑架构图: MySQL逻辑架构大概可以分为三层: 客户端:最上层的服务并不是MySQL所独有的,大多数基于网络的客户端/服 ...

  10. BUAA_2021_SE_READING_#2

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 个人阅读作业#2 我在这个课程的目标是 通过课程学习,完成第一个可以称之为"软件"的项目 ...