码龄10年 暂无认证

34102
访问
1
等级

8
获赞
3
评论

最新评论

  • 20240228阿⑤

    积分乍获得

  • 20231124ziher

    666

  • 20230909八月老师

    什麼時候發佈易語言支持庫呢

一.《WIN32》try_except异常深入

Heart 2023-05-24 10:05:10 发布 368

分类专栏: 开发技术 文章标签: try_except 异常

__try_except异常深入

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

2. SEH的异常处理模型主要由try-except语句来完成,与标准的try catch相似。

3.C++异常处理模型使用catch关键字来定义异常处理模块,而SEH是采用__except关键 字来定义

4.catch关键字后面往往好像接受一个函数参数一样,可以是各种类型的异常数据对象;catch(MyException& e)

5.__except关键字则不同,它后面跟的却是一个表达式(函数调用也可以是一个表达式)


案例分析

1.利用APIGetExceptionCode()获取异常代码

2.except参数的值有以下三种:

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

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

EXCEPTION_EXECUTE_HANDLER (1) 异常已经被识别,控制流将进入到__except模块中运行异常处理代码 try-except的关键是如何在__except模块中获得异常错误的相关信息.

3.DWORD GetExceptionCode(VOID); // 取得异常编号 例如:EXCEPTION_ACCESS_VIOLATION 访问权限

4.GetExceptionInformation()返回更丰富的信息返回一个EXCEPTION_POINTERS结构体地址这个结构体在TIB结构中存储为一个异常链表中

typedef struct _EXCEPTION_POINTERS
{ 
   PEXCEPTION_RECORD ExceptionRecord;//记录了一些与异常相关的信息
   PCONTEXT ContextRecord;
   //记录了异常发生时,线程当时的上下文环境,主要包括寄存器的值
   //有了这些信息,__except模块便可以对异常错误进行很好的分类和恢复处理,通常我们需要一个过滤函数来辅助
} EXCEPTION_POINTERS;
typedef struct _EXCEPTION_RECORD
{
  00h  DWORD                     ExceptionCode;      //异常事件码
  04h  DWORD                     ExceptionFlags;     //标志
  08h  struct _EXCEPTION_RECORD  *ExceptionRecord;   //下一个EXCEPTION_RECORD结构地址
  0ch  PVOID                     ExceptionAddress;   //异常发生的地址
  10h  DWORD                     NumberParameters;   //ExceptionInformation的dword数目
  14h  ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
}EXCEPTION_RECORD;
typedef     EXCEPTION_RECORD        *PEXCEPTION_RECORD;
#define     EXCEPTION_MAXIMUM_PARAMETERS    15

5.编写一个过滤函数

int exception_access_violation_filter(LPEXCEPTION_POINTERS p_exinfo)//GetExceptionInformation获取这个结构体地址传进来
{
    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处理这个异常
}

6.调用GetExceptionInformation

__try
{
   // guarded code
}
__except(exception_access_violation_filter(GetExceptionInformation()))
{
  //
}

7.调用GetExceptionCode

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; 
}

SEH异常处理模型中,也可以抛出一个异常

1.对应的WindowsAPI函数是RaiseException,

VOID RaiseException( DWORD dwExceptionCode, // 异常的编号 DWORD dwExceptionFlags, // 异常标记 DWORD nNumberOfArguments, // 参数个数 CONST DWORD *lpArguments // 参数数组首地址 ); 通常,后三个参数基本不用 SEH异常处理还有try-finally

2. SEH异常处理模型中,异常通过RaiseException()函数抛出。

3.RaiseException()函数的作用类似于C++异常模型中的throw。

4.用try-except语法,与C++异常模型相似,try-except也支持多层的try-except嵌套。

5.try-except模型中,一个try块只能是有一个except块;而C++异常模型中,一个try块可以有多个catch块。 C++异常模型是按照异常对象的类型来进行匹配查找的;

6.而try-except模型则不同,它通过一个表达式的值来进行判断. __except关键字后面跟的表达式,它可以是各种类型的表达式,

例如,它可以是一个函数调用,或是一个条件表达式,或是一个逗号表达式,或干脆就是一个整 型常量等等。

关于SEH更详细的可以《windows核心编程》

Heart1
0 0 上传作业
X
    网友评论 0条评论 0人参与
    请登陆会员1

    表情

    评论列表

×