看流星社区

 找回密码
 注册账号
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
赞助广告位 请点击这里联系站长 QQ20209081
赞助广告位 请点击这里联系站长 QQ20209081
赞助广告位 请点击这里联系站长 QQ20209081
查看: 34|回复: 0

VC++ 异常处理 __try __except的用法

[复制链接]

该用户从未签到

发表于 2020-3-22 19:12:18 | 显示全部楼层 |阅读模式

__try __except的用法:

__try __except是windows 系统独有的异常处理模型,称为SEH( structured exception handling ),SEH的异常处理模型主要由__try __except语句来完成,与标准的try catch相似。

与C++异常处理模型使用catch关键字来定义异常处理模块,而SEH是采用__except关键字来定义;并且catch关键字后面往往接受一个函数参数,可以是各种类型的异常数据对象;

而 __except关键字则不同,它后面跟的却是一个表达式。

例子:
  1. long WINAPI FilterFunc(DWORD dwExceptionCode)
  2. {
  3.    return (dwExceptionCode ==
  4.    STATUS_STACK_OVERFLOW) ?
  5.    EXCEPTION_EXECUTE_HANDLER :
  6.   EXCEPTION_CONTINUE_SEARCH;
  7. }

  8. UINT WINAPI ThreadFunc(LPVOID param)
  9. {
  10.   __try
  11.  {
  12.        // guarded code
  13.  }
  14.  __except (FilterFunc(GetExceptionCode()))
  15.  {
  16.    // 如果是栈溢出,进行处理。
  17.   }
  18. return 0;
  19. }
复制代码



except参数的值有以下三种:

EXCEPTION_CONTINUE_EXECUTION (–1):          异常被忽略,控制流将在异常出现的点之后,继续恢复运行。
EXCEPTION_CONTINUE_SEARCH (0):                 异常不被识别,也即当前的这个__except模块不是这个异常错误所对应的正确的异常处理模块。
                                                                        系统将继续到上 __try __except域中继续查找一个恰当的__except模块。
EXCEPTION_EXECUTE_HANDLER (1):                异常已经被识别,控制流将进入到__except模块中运行异常处理代码



__try __except的关键是如何在 __except模块中获得异常错误的相关信息?

Windows提供了两个API函数来获取异常信息:
  1. LPEXCEPTION_POINTERS GetExceptionInformation(VOID); //取得异常相关信息
  2. DWORD GetExceptionCode(VOID); // 取得异常编号
复制代码



EXCEPTION_POINTERS结构如下,
  1. typedef struct _EXCEPTION_POINTERS
  2. { // exp
  3. PEXCEPTION_RECORD ExceptionRecord;

  4. PCONTEXT ContextRecord;

  5. } EXCEPTION_POINTERS;
复制代码


EXCEPTION_RECORD类型,它记录了一些与异常相关的信息;

CONTEXT数据结构体中记录了异常发生时,线程当时的上下文环境,主要包括寄存器的值。

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

  1. int exception_access_violation_filter(LPEXCEPTION_POINTERS p_exinfo)
  2. {
  3.     if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
  4.     {
  5.         messagebox("access vialation exceptionn");

  6.        return EXCEPTION_EXECUTE_HANDLER ; //告诉except处理这个异常
  7.     }
  8.     else
  9.     {
  10.      return EXCEPTION_CONTINUE_SEARCH; //不告诉except处理这个异常
  11.     }
  12. }

  13. int exception_int_divide_by_zero_filter(LPEXCEPTION_POINTERS p_exinfo)
  14. {
  15.     if(p_exinfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
  16.     {
  17.         return  EXCEPTION_EXECUTE_HANDLER; //告诉except处理这个异常
  18.     }
  19.    else
  20.    {
  21.     return EXCEPTION_CONTINUE_SEARCH; //不告诉except处理这个异常
  22.    }
  23. }
复制代码



于是,可以这样写这段异常处理代码:
  1. __try
  2. {

  3.   // guarded code

  4. }

  5. __except(exception_access_violation_filter(GetExceptionInformation()))
  6. {

  7. //在此可以调用BugReport程序

  8. }
复制代码




SEH异常处理模型中,也可以抛出一个异常。对应的WindowsAPI函数是RaiseException,
  1. VOID RaiseException(
  2. DWORD dwExceptionCode, // 异常的编号
  3. DWORD dwExceptionFlags, // 异常标记
  4. DWORD nNumberOfArguments, // 参数个数
  5. CONST DWORD *lpArguments //  参数数组首地址
  6. );
复制代码




通常,后三个参数基本不用 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。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2020-3-31 00:40

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表