Windows平台下异常处理(二) - 结构化异常

Windows结构化异常在《Windows核心编程》中有大量篇幅做了介绍,这里面介绍的内容都基于书中的内容和自己的理解与研究。其实,在windows平台下,C++和C#的异常处理都是依靠Windows的结构化异常来实现的,大家可以依靠VS Debug来查看具体的信息.

Windows结构化异常介绍

Windows的结构化异常的大量实现是有操作系统和编译器共同完成的,其主要分为终止处理(termination handling)和异常处理(exception handling)两部分。

  • 终止处理程序:终止处理程序确保不管一代代码是如何退出的,梁歪一个代码块都可以(终止处理程序)都可以被执行,一般情况下确保资源的释放,终止程序的基本语法如下:
  __try{
    // Guarded body 可能出现异常的代码
    }
    __finally{
    // 终止处理程序
    }
  • 异常处理程序: 当一个硬件或者软件异常被抛出时,windows系统会给我们的应用程序一个查看和处理异常的机会,并允许应用程序自己处理这个异常,基本代码为:
__try{
 // Guarded body 可能异常处理的程序
}
__except(exception_filter){
// exception handling 异常处理函数
}

语法上需要注意的是: 任何一个__try块,后面必须跟一个finally代码块或者except代码块,但是不能同时有finally块和except块,或者同时有多个finally块或者except块。不过却可以将try-finally块嵌套到try-except块中,具体用法可以参考后面的例子程序。

如何实现结构化异常

在这里大致介绍一个结构化异常是如何实现的,要了解结构化异常怎么实现,可以参考网页:http://www.codeproject.com/Articles/2126/How-a-C-compiler-implements-exception-handling
可以介绍一下的具体的基础内容:
a) Stack Overview:函数调用堆栈
我们先看一个没有异常的函数调用堆栈, 详细看下图:
这里写图片描述
从函数的调用堆栈中,我们可以看出函数的调用关系为:foo->bar->widget.

b) EXCEPTION_REGISTRATION - 异常处理结构体
Windows 下有一个结构体为EXCEPTION_REGISTRATION ,用于保存异常的处理程序,基本的结构 :

struct EXCEPTION_REGISTRATION
{
EXCEPTION_REGISTRATION *prev;
DWORD handler;
int id;
DWORD ebp;
};
从字面上可以理解为,异常处理程序应该是通过链表组织起来。

c)Function Info
这里写图片描述

d)FS:[0]
FS 是一个线程堆栈寄存器,具体内容可以参考http://en.wikipedia.org/wiki/Win32_Thread_Information_Block

e)Stack with exception
这里写图片描述
- 基本的代码示例
大家可以通过下面的代码体会 windows下的__try, __except, __finally EXCEPTION_EXECUTE_HANDLER, EXCEPTION_CONTINUE_SEARCH,EXCEPTION_CONTINUE_EXECUTION, 的用法。其实C#的异常处理应该是基于上述关键字实现的。

#include "stdafx.h"
#include <Windows.h>
DWORD FilterFunction() 
{ 
    printf("1 ");                     // printed first 
    //return EXCEPTION_EXECUTE_HANDLER; 
    //return EXCEPTION_CONTINUE_SEARCH;
    return EXCEPTION_CONTINUE_EXECUTION;
} 

int _tmain(int argc, _TCHAR* argv[])
{
    __try 
    { 
        __try 
        { 
            RaiseException( 
                1,                    // exception code 
                0,                    // continuable exception 
                0, NULL);             // no arguments 

          printf("4\n");                // this is printed last 
        } 
        __finally 
        { 
            printf("2 ");             // this is printed second 
        }

    }
    //__except (EXCEPTION_CONTINUE_SEARCH)
    //{
    //  printf("Test\n");                // this is printed last 
    //}
    __except ( FilterFunction()) 
    { 
        printf("3\n");                // this is printed last 
    }

   return 0;
}

异常与调试器

对于下列windows的错误报告,你能想到什么:
这里写图片描述

其实是windows Error Report中增加了调试的支持,具体的内容请查看下面流程图(来自《windows核心编程):
这里写图片描述

在讨论Windows Error Report的处理流程前,请看下面的用调试器等到的调用堆栈:
这里写图片描述
在这里要讨论具体的UnhandledExceptionFilter函数的处理大致流程如下:
1)将未处理的异常报告通知给调试器
UnhandledExceptionFilter函数首先检查当前程序是不是在调试器的控制下,如果是,将通知调试器,调试器根据通知的消息定位代码与调用堆栈。
2) 通知给我们设置的全局异常过滤函数
如果应用程序已经调用SetUnhandledExceptionFilter,其会调用该函数,一般来讲,该函数可以用于保存堆栈信息,以便于调试和解决问题。
3)将未处理的异常再次报告给调试器
4)终止进程

具体详细的内容,请参考 《Windows 核心编程》 一书。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值