zoukankan      html  css  js  c++  java
  • 驱动下的异常处理

    try-except用法

      try except是windows 系统独有的异常处理模型,windows的异常处理模式,称为SEH( structured exception handling ),

           SEH的异常处理模型主要由try-except语句来完成,与标准的try catch相似。与C++异常处理模型使用catch关键字来定义异常处理模块,而SEH是采用__except关键

    字来定义。并且,catch关键字后面往往好像接受一个函数参数一样,可以是各种类型的异常数据对象;但是__except关键字则不同,它后面跟的却是一个表达式.

    我们知道,函数调用也是一个表达式。

        我们来看下面这个例子,这个例子是用来处理栈溢出的异常。   

    int *p = NULL;  //定义一个空的指针,因为空指针式只能读不能写的!
    
    void Error_Test(){
        int i = 100;
        __try{
            *p = i;  //我们给空指针赋值看看,是不是不能写,看能不能报错.
        }
        __except(1){
            
            /*********************************************************
            __except(filter_Value) 参数取值:
             EXCEPTION_CONTINUE_SEARCH; 0 转向上一层异常处理;
            EXCEPTION_CONTINUE_EXECUTION - 1 重复执行错误指令;
            EXCEPTION_EXECUTE_HANDLER 1  忽略该错误转到 __except 块处理; 
            **********************************************************/
            
            KdPrint(("---错误代码已处理---"));
        }
        return;
    }
    
    void Output_Assert(){
        //断言
        ASSERT(p != NULL); //判断的条件结果为假就抛出断言,也可手动强制抛出断言:ASSERT(false);
        return;
    }

    我们用 Windbg 进行双击调试,看看它抛出的异常信息是什么

    如图:

    image

    如图上的说明!!

    我们也可以输入 Windbg 给出的建议,Break repeatedly 断开调试,并重复抛出后面的异常;或者  Break Once ,断开调试,只抛出这一次的异常;或者输入 Ignore ,忽略异常,让系统和驱动继续运行;terminate  process 终止进程运行;terminate  process 终止线程运行。

    我们输入 Ignore 忽略异常!

    image

    驱动忽略异常,并继续加载!

    第二个例子:

    long WINAPI FilterFunc(DWORD dwExceptionCode)

    {

    return (dwExceptionCode == STATUS_STACK_OVERFLOW) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;

    }

    UINT WINAPI ThreadFunc(LPVOID param)

    {

    __try

    {

                       // guarded code 

    }

    __except (FilterFunc(GetExceptionCode()))

    {

    // 如果是栈溢出,进行处理。

    }

        return  TRUEt;    

    }

    except参数的值有以下三种:

           EXCEPTION_CONTINUE_EXECUTION (–1)     异常被忽略,控制流将在异常出现的点之后,继续恢复运行。

      EXCEPTION_CONTINUE_SEARCH (0)          异常不被识别,也即当前的这个__except模块不是这个异常错误所对应的正确的异常处理模块。系统将继续到上一try-

    except域中继续查找一个恰当的__except模块。

      EXCEPTION_EXECUTE_HANDLER (1)         异常已经被识别,控制流将进入到__except模块中运行异常处理代码

    try-except的关键是如何在__except模块中获得异常错误的相关信息.

    Windows提供了两个API函数来获取异常信息:

    LPEXCEPTION_POINTERS GetExceptionInformation(VOID); //取得异常相关信息

    DWORD GetExceptionCode(VOID); // 取得异常编号

    GetExceptionCode()返回异常编号,而GetExceptionInformation()返回更丰富的信息,EXCEPTION_POINTERS结构如下,

    typedef struct _EXCEPTION_POINTERS { // exp 

    PEXCEPTION_RECORD ExceptionRecord; 

    PCONTEXT ContextRecord; 

    } EXCEPTION_POINTERS;

    其中EXCEPTION_RECORD类型,它记录了一些与异常相关的信息;而CONTEXT数据结构体中记录了异常发生时,线程当时的上下文环境,主要包括寄存器的值。

    有了这些信息,__except模块便可以对异常错误进行很好的分类和恢复处理,通常我们需要一个过滤函数来辅助。

    一般称为是filterfunction.过滤函数只过滤需要处理的异常。

    int exception_access_violation_filter(LPEXCEPTION_POINTERS p_exinfo)

    {

        if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)

        {

            messagebox("access vialation exceptionn");

           return EXCEPTION_EXECUTE_HANDLER ; //告诉except处理这个异常

        }

        else return EXCEPTION_CONTINUE_SEARCH; //不告诉except处理这个异常

    }

    int exception_int_divide_by_zero_filter(LPEXCEPTION_POINTERS p_exinfo)

    {

        if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)

        {

            return  EXCEPTION_EXECUTE_HANDLER; //告诉except处理这个异常

        }

       else return EXCEPTION_CONTINUE_SEARCH; //不告诉except处理这个异常

    }

     

    于是,你可以这样写这段异常处理代码:

    __try

    {

      // guarded code

    }

    __except(exception_access_violation_filter(GetExceptionInformation()))

    {

    //

    }

    __try

    {

      // guarded code

    }

    __exceptexception_int_divide_by_zero_filter(GetExceptionInformation()))

    {

    //exception handling

    }

    SEH异常处理模型中,也可以抛出一个异常。对应的WindowsAPI函数是RaiseException,

    VOID RaiseException(

    DWORD dwExceptionCode, // 异常的编号

    DWORD dwExceptionFlags, // 异常标记

    DWORD nNumberOfArguments, // 参数个数

    CONST DWORD *lpArguments //  参数数组首地址

    );

    通常,后三个参数基本不用

    SEH异常处理还有try-finally.类似于java里的try-catch-finally.但是SEH的try只能和except和finally两者之间的一个搭配,不能有try-except-finnaly. 

    C++异常模型用try-catch语法定义,而SEH异常模型则用try-except语法,与C++异常模型相似,try-except也支持多层的try-except嵌套。

    try-except模型中,一个try块只能是有一个except块;而C++异常模型中,一个try块可以有多个catch块。

    C++异常模型是按照异常对象的类型来进行匹配查找的;而try-except模型则不同,它通过一个表达式的值来进行判断.

      __except关键字后面跟的表达式,它可以是各种类型的表达式,例如,它可以是一个函数调用,或是一个条件表达式,或是一个逗号表达式,或干脆就是一个整

    型常量等等。最常用的是一个函数表达式,并且通过利用GetExceptionCode()或GetExceptionInformation ()函数来获取当前的异常错误信息,便于程序员有效控制异常

    错误的分类处理。

    SEH异常处理模型中,异常通过RaiseException()函数抛出。RaiseException()函数的作用类似于C++异常模型中的throw。

    关于SEH异常处理更详细的资料,你可以去看windows via c/c++这本书,中文译名是windows核心编程。不过还是建议你看英文原版,翻译的版本质量不高。

  • 相关阅读:
    leetcode Remove Linked List Elements
    leetcode Word Pattern
    leetcode Isomorphic Strings
    leetcode Valid Parentheses
    leetcode Remove Nth Node From End of List
    leetcode Contains Duplicate II
    leetcode Rectangle Area
    leetcode Length of Last Word
    leetcode Valid Sudoku
    leetcode Reverse Bits
  • 原文地址:https://www.cnblogs.com/lfls128/p/5023357.html
Copyright © 2011-2022 走看看