本文大部分来自《windows核心编程》。

例1

//二话不说,直接上代码int Funcenstein2()
{__try{return 3;}__finally{//在函数返回之前会处理__finally里的内容cout<<"finally executed"<<endl;}return 4;//此函数返回3而不是4
}

通过使用终止处理程序可以防止过早的执行return语句。当return语句试图退出try块的时候,编译器会让finally代码在它。即编译器保证finally代码块在出try块的时候return之前执行。

者可以想知道,编译器是如何保证此功能的呢?原来当编译器检查程序代码时,会发现try代码里有一个return语句。于是,编译器就会生成一些代码先将返回值(例子中的 3)保存在一个由它创建的一个临时变量里,然后再执行finally语句块。这个过程被称之前为局部展开(LOCAL UNWIND)。更确切的说,当系统因try代码提前退出finally时就会发生局部展开。一旦finally代码块执行完毕,编译器所创建的临时变量值就会返回给函数调用者。

由此可见,为了让整个机制运行起来,编译器必须生成一些额外的代码,而系统也要很执行一些额外的工作。在不同的cpu结构上,让终止处理工作起来的步骤也不同。需要注意的是,应该避免在try代码中使用return语句,因为这是对程序性能有害的。__leave关键字,它可以帮助我们发现那些有局部展开开销的代码

例2

int Funcenstein3()
{//在try中使用goto语句时,就会产生局部展开以执行finally代码块。//这一次当finally执行完之后。因为try和finally中都没有函数返回语句,//所以ReturnValue标签后面的代码也会执行。因此这函数返回4。//但是由于代码破坏了try块到finally的正常执行流程,可能有比较大的性能损失,其程序取决于cpu体系结构。int ret=0;__try{ret=5;goto ReturnValue;}__finally{cout<<"finally executed"<<endl;}
ReturnValue:return 4;
}

例3

在这个例子中,终止处理将真正证明它的价值。首先看一下代码

DWORD Funcfurter1()
{DWORD dwTemp;//1. do any processing here
__try{WaitForSingleObject(g_hSem,INFINITE);dwTemp=Funcinator(g_dwProtectedData);}__finally{ReleaseSemaphore(g_hSem,1,NULL);}return dwTemp;
}

假设try代码块中Funcinator函数存在一个缺陷会导致程序访问非法的内存。如果没有SEH这种情况下最络导致Windows错误报告(WER)弹出一个对话框:“Application has stopped working”。这个对话框在Windows上经常可以见到。一旦用户取消这个对话框,进程就会终止。但信号量依然被占用并再也得不到释放。其他进程中的纯种就会因为无休止的等待这个信号量而得不到CPU时间片。如果把信号量放在finally之中,即使用try中调用的函数发生了内存访问违规这样的异常,这个信号量也可以被释放。但是,请注意,从Windows Vista开始,须显式地保护try/finally框架,以确保在异常抛出时,finally代码会执行。

例4

现在不防做一个实验,判断一下这个函数的返回值

DWORD FuncalDoodLeDoo()
{DWORD dwTemp=0;while (dwTemp<10){__try{if(dwTemp==2)continue;if(dwTemp==3)break;}__finally{dwTemp++;}dwTemp++;}dwTemp+=10;return dwTemp;
}

让我们逐步分析这个函数执行的过程:一开始将dwTemp赋值为0,然后try块中的代码开始执行,但是两个if语句都为false。于是程序正常进入到finally代码块,在这里给dwTemp的值上加1,而finally块后面的代码又将dwTemp加1。

下一次循环开时,dwTemp=2,第一个if为true,程序试如果没有__finally程序会跳到while条件判断处执行,但dwTemp值班不会改变,这将会是一个死循环。但是现在我们有终止处理程序,系统注意到continue语句将会导致提前跳出try块,于是强制执行finally语句块。 在finally语句块中dwTemp被增加到3.这次finally之后的代码块没有机会执行。因此finally执行完之后程序跳到循环顶部执行。

现在我们分析第三次迭代,这次第一个if判断表达式的值为false,第二个表达式的值为true,系统再次侦测到程序流想要提前跳出try块,于是调用finally代码块,这里的dwTemp增加到4.因为break语句的执行程序控制流从whhile循环后开始继续。因而finally块之后循环以内的代码就不会被执行了。而循环之后的代码将dwTemp的值设置为14。这是程序最终返回的结果。不用我指明,请教也不会写出FuncalDoodleDoo这样的代码。此处只是为了演示终止处理程序是如何工作的。‘

绝大多数部情况下,try块中的提前退出都会被终止处理程序所捕获,但是在进程或线程提前终止的情况下,系统没法保证finally代码块的执行。调用ExitThread或者ExitProcess可以马上终止纯种或进程,而不会引发finally执行。同样如果当前纯种或者进程因为另一个程序调用TerminateThread或TerminateProcess而不得不结束,finally代码块也不会被执行,有一些c运行期函数比如(abort),因为在其内部最络调用的是ExitProcess,也会导致finally块不能执行。我们没法阻止别的线程杀死我们的线程或进程,但是可以在自己的代码中尽量避免对ExitThread或ExitProces的草率调用。

例5

DWORD Funcenstein4()
{DWORD dwTemp;//1. do any processing here
    __try{WaitForSingleObject(g_hSem,INFINITE);g_dwProcectedData=5;dwTemp=g_dwProcectedData;//return the new valuereturn dwTemp; }__finally{ReleaseSemaphore(g_hSem,1,NULL);return 103;}dwTemp = 9;return dwTemp;
}

在上面的函数中,try中的代码试图用return 返回给调用者。正如我们前面提到的那样,试图在try块中提前退出函数导致编程器生成一些额外代码,将函数返回结果保存在一个临时变量中,然后执行finally中又多了一个return,那么导致103被写入到编译器生成的临时变量时。从而覆盖了原先的值5。而返回103

windows终止处理程序( __try __finally) 简单解析相关推荐

  1. windows终止处理程序( __try __finally) 简单解析

    本文大部分来自<windows核心编程>. 例1 //二话不说,直接上代码int Funcenstein2() {__try{return 3;}__finally{//在函数返回之前会处 ...

  2. C++及Windows异常处理(try,catch; __try,__finally; __try, __except)——一道笔试题引起的探究

    题目: int* p = 0x00000000; // pointer to NULL puts( "hello "); __try{ puts( "in try &qu ...

  3. [ 转载 ] Java基础10--关于Object类下所有方法的简单解析

    关于Object类下所有方法的简单解析 类Object是类层次结构的根类,是每一个类的父类,所有的对象包括数组,String,Integer等包装类,所以了解Object是很有必要的,话不多说,我们直 ...

  4. memcache的windows下的安装和简单使用

    原文:memcache的windows下的安装和简单使用 memcache是为了解决网站访问量大,数据库压力倍增的解决方案之一,由于其简单实用,很多站点现在都在使用memcache,但是memcach ...

  5. boost::stacktrace模块实现终止处理程序的测试程序

    boost::stacktrace模块实现终止处理程序的测试程序 实现功能 C++实现代码 实现功能 boost::stacktrace模块实现终止处理程序的测试程序 C++实现代码 #include ...

  6. 插件化框架DL源码的简单解析

    目前行业内已经有较多的插件化实现方案.本文主要对DL(DynamicLoadApk)这一个开源的侵入式插件化方案进行简单分析.因为Service组件插件化的实现逻辑和Activity大体相似,所以在这 ...

  7. java 解析xls 文件_java简单解析xls文件的方法示例【读取和写入】

    本文实例讲述了java简单解析xls文件的方法.分享给大家供大家参考,具体如下: 读取: import java.io.*; import jxl.*; import jxl.write.*; imp ...

  8. java在线打开xml文件_java实现简单解析XML文件功能示例

    本文实例讲述了java实现简单解析XML文件功能.分享给大家供大家参考,具体如下: package demo; import java.io.File; import java.io.IOExcept ...

  9. 开源并兼容Windows NT的操作系统ReactOS简单介绍

    **************************************************************************************************** ...

  10. java:AXIS调用webService接口,返回String类型xml,并用dom4j简单解析xml

    一.使用axis调用webService接口,返回String类型xml 1.导入axis依赖 2.直接贴代码 /*** 调用webservice接口的方法,并返回String类型的xml* @par ...

最新文章

  1. ROS知识:分析和改写小乌龟代码【01】
  2. Composite UI Application Block学习笔记之Event Broker
  3. MySQL存储引擎--MYSIAM和INNODB引擎区别
  4. treetable怎么带参数_Layui实现TreeTable(树形数据表格)
  5. 【CCNA题库】Ti CCNA640-802V30版题库
  6. B02 - 025、使用Hive配置mysql作为元数据库
  7. DDoS 报告攻击类型占比
  8. springBoot学习笔记(6)——@Valid和@Validated的使用
  9. 从程序员角度看心理学中的恐慌区、学习区和舒适区
  10. Java九十条经验法则之第三条:用私有构造器或者枚举类型强化Singlen对象
  11. java web之javascript(js)解析
  12. cps配置之唯品会联盟篇
  13. 通过 Flowable-UI 来体验一把 Flowable 流程引擎
  14. 虚拟土地价格暴跌85% 房地产泡沫破裂?依托炒作的暴富游戏需谨慎参与
  15. markdown常用数学符号小结⌈ ⌉⌊ ⌋
  16. 磕磕碰碰3个月,作为一名程序媛我的找工作经历,终于进了字节!!!
  17. Vue+SpringBoot打造学生综合素质评价系统
  18. PTA 7-3 推算星期
  19. 58帮帮电脑版 v3.2.1 官方最新版
  20. 生僻汉字结构数字键编码

热门文章

  1. Enterprise Solution(2.2.20130525) 解决方案配置与源代码下载
  2. DevExpress控件的GridControl控件小结
  3. GridView合并表头多重表头无错完美版(以合并3列3行举例)
  4. 红帽学习笔记[RHCSA] 第七课[网络配置相关]
  5. MySql事务及ACID实现的原理
  6. 无限分级函数 简单 引用绑值
  7. MSP430 PIN 操作寄存器
  8. mysqldump怎么用 mysqldump没反应 mysqldump语法错误 mysqldump备份 mysql恢复 source命令 采用Navicat备份与mysqldump备份的区别...
  9. SpringData-JPA
  10. Mac端SVN工具CornerStone详解