zoukankan      html  css  js  c++  java
  • Windows核心编程 第23章 结束处理程序

    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 ht 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 ol o n g j u m pc o n t i n u eb r e a kr 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 1t 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 1f i n a l l y块执行。下一章将详细讨论全局展开。

    由于以上三种情况中某一种的结果而导致f i n a l l y块中的代码开始执行。为了确定是哪一种情况引起f i n a l l y块执行,可以调用内部函数(或内蕴函数,intrinsic functionAbnormal 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 or e t u r nb r e a kc 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对话框。


     

     

  • 相关阅读:
    设置maven阿里云镜像和公司私服并存
    idea favorites bookmarks标签收藏夹数据丢失bug
    C#后期绑定调用COM组件
    SQL Studio 1.0:一款轻便的SQL脚本工具兼容SQL Server、MySQL、Access2007
    SQL Studio 2.0: 新版发布
    SQLHelper用的不爽,试试CmdRunner吧
    Flask + uWSGI+ Linux 指南及避坑
    Flask + Pyinstaller 打包后运行报错 SystemError
    Url重写之UrlRewriter
    .net5 提取压缩包内指定文件内容无需解压
  • 原文地址:https://www.cnblogs.com/csnd/p/12062097.html
Copyright © 2011-2022 走看看