zl程序教程

您现在的位置是:首页 >  系统

当前栏目

Windows 异常

2023-09-27 14:25:17 时间

    写在前面的话:

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

    异常的发生:

    在程序编写过程中。异常会时有发生,比方常见的遇到了除 0 异常,空指针异常,野指针异常等等。

这些异常大家可能都耳熟能详,除 0 异常非常easy,数学上除 0 是没法运算的,计算机中同理。

后两种异常可能大家平时都仅仅知其表,我们能够简单的理解为,空指针异常是由于地址为空的内存是保留内存。专门为程序用来进行指针初始化使用的。当指针初始化为 NULL时。表明这个指针不代表不论什么东西。且不能使用。野指针异常则是,指针指向了一段不能使用的内存,产生了訪问违例。

    异常的处理:

    当遇到前两种异常时,程序是非常easy处理的,由于通过程序推断,除数为 0 或者指针为空,就能够把这些异常扼杀在萌芽之中,可是野指针异常却非常难处理。假设遇到这个问题。我们通常的做法是,将这个异常捕获,并通知开发者,进行分析野指针产生的原因,那么假设捕获这些异常呢?

    异常的捕获:

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

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

    1.      它的基于线程的。由于是在堆栈中保存的信息;

    2.      它是基于 __try, __except keyword来标识的;

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

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

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

    它是通过 APIAddVectoredExceptionHandler 来注冊的。它也能够反复调用,且异常处理函数也将形成一个链表,链表头的异常处理代码也将会先运行。

但它具有下面特点。

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

    2.      它不须要 __try, __except keyword来标识。通过函数调用。

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

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