码迷,mamicode.com
首页 > Windows程序 > 详细

Windows 异常

时间:2014-10-09 15:08:34      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:seh   veh   异常捕获   

    写在前面的话:

    这里的标题是Windows 的异常,所以这里已明确告知,其实异常是一个系统行为,而我们以前经常听到的 C++ 异常,Java 异常,等等都是建立在这基础之上,重新形成的自己的框架,所以 Windows 的异常是它们的基础。

    异常的发生:

    在程序编写过程中,异常会时有发生,比如常见的遇到了除 0 异常,空指针异常,野指针异常等等。这些异常大家可能都耳熟能详,除 0 异常很简单,数学上除 0 是没法运算的,计算机中同理。后两种异常可能大家平时都只知其表,我们可以简单的理解为,空指针异常是因为地址为空的内存是保留内存,专门为程序用来进行指针初始化使用的,当指针初始化为 NULL时,表明这个指针不代表任何东西,且不能使用。野指针异常则是,指针指向了一段不能使用的内存,产生了访问违例。

    异常的处理:

    当遇到前两种异常时,程序是很容易处理的,因为通过程序判断,除数为 0 或者指针为空,就可以把这些异常扼杀在萌芽之中,但是野指针异常却很难处理,如果遇到这个问题,我们通常的做法是,将这个异常捕获,并通知开发人员,进行分析野指针产生的原因,那么如果捕获这些异常呢?

    异常的捕获:

    早先在 Winodws 上采用的方法是结构化异常处理,也即 SEH 。就是我们经常采用的 __try, __except 等关键字来合包围的异常块和处理块,当 __try 块中的代码发生异常时,根据异常筛选,就会跳入到 __except 块。这种异常处理还是相当灵活的,它可以嵌套存在,即 __try 块中的代码还有可能调用到含有另一个 __try 块的函数或代码。为了完成这样的功能,编译器其实巧妙地使用了栈来保留这些信息,简单点理解就是,当遇到 __try 块时,就在当时栈中记录下它的异常处理函数的地址,当函数再次遇到 __try 时,再次压栈,当 __try 块执行完毕时,从栈中弹出这个值,即,__try 块就相当于函数调用一般,这些信息完美地保存在了栈中,并且形成一个链表。那么当遇到一个异常,最后一次入栈的捕获的信息将会得到处理。如果它返回继续搜索,那么链表中的每个异常捕获的代码将会依次执行。

    那么我们会看到它的几个特点:

    1.      它的基于线程的,因为是在堆栈中保存的信息;

    2.      它是基于 __try, __except 关键字来标识的;

    3.      后写和 __try 永远会先执行。

    看似完美的方案,其它是存在缺点的,假如我们想捕获到没有处理的异常,并输出日志,你可能会选择在最外层函数,有可能是 main 函数包含一个 __try 块,但如果你调用的代码中,有一段代码是第三方的,且它也有自己的 __try 块,并且发生异常时,它的处理异常的手段是,发生了异常就退出程序,那么,你的异常捕获代码永远也得不到执行。

    所以在 XP 之后,Windows 又引入了另一种异常处理的方式,叫做 VEH, 即向量化异常捕获。

    它是通过 APIAddVectoredExceptionHandler 来注册的,它也可以重复调用,且异常处理函数也将形成一个链表,链表头的异常处理代码也将会先执行。但它具有以下特点。

    1.      它是基于进程的,也相当于全局的;

    2.      它不需要 __try, __except 关键字来标识,通过函数调用;

    3.      它会在SEH 机制之前先得到异常处理权。

    基于这些特点,写出自己的异常捕获的库,我想也只是时间的问题了。还有一种叫做 VCH ,在 64 位系统上会有支持,可以自行查阅一下相关资料。

Windows 异常

标签:seh   veh   异常捕获   

原文地址:http://blog.csdn.net/henzox/article/details/39929417

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!