`
qoz790qo
  • 浏览: 15011 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

异常处理

 
阅读更多

异常处理
2010年07月23日
  下面的代码举例说明了一种方法,指出所发生异常的类别: 
  BOOL Func_SEHExceptionGetCodeBase() 
  { 
  int x,y; 
  __try{ 
  x = 0; 
  y = 4/x; 
  } 
  __except((GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) ? \ 
  EXCEPTION_EXECUTE_HANDLER :\ 
  EXCEPTION_CONTINUE_SEARCH) 
  { 
  file://handle divide by zero exception 
  } 
  } 
  GetExceptionCode返回一个值,该值指出所发生异常的种类: 
  下面列出所有预定义的异常和相应的含意,这些内容取自Platform SDK文档。这些异常标识符可以在WinBase.h文件中找到。我们对这些异常做了分类。 
  1. 与内存有关的异常 
  E X C E P T I O N _ A C C E S S _ V I O L AT I O N。线程试图对一个虚地址进行读或写,但没有做适当的存取。这是最常见的异常。 
  E X C E P T I O N _ D ATAT Y P E _ M I S A L I G N M E N T。线程试图读或写不支持对齐( a l i g n m e n t)的硬件上的未对齐的数据。例如, 1 6位数值必须对齐在2字节边界上,3 2位数值要对齐在4字节边界上。 
  E X C E P T I O N _ A R R AY _ B O U N D S _ E X C E E D E D。线程试图存取一个越界的数组元素,相应的硬件支持边界检查。 
  E X C E P T I O N _ I N _ PA G E _ E R R O R。由于文件系统或一个设备启动程序返回一个读错误,造成不能满足要求的页故障。 
  E X C E P T I O N _ G U A R D _ PA G E。一个线程试图存取一个带有PA G E _ G U A R D保护属性的内存页。该页是可存取的,并引起一个E X C E P T I O N _ G U A R D _ PA G E异常。 
  EXCEPTION_STA C K _ O V E R F L O W。线程用完了分配给它的所有栈空间。 
  E X C E P T I O N _ I L L E G A L _ I N S T R U C T I O N。线程执行了一个无效的指令。这个异常由特定的C P U结构来定义;在不同的C P U上,执行一个无效指令可引起一个陷井错误。 
  E X C E P T I O N _ P R I V _ I N S T R U C T I O N。线程执行一个指令,其操作在当前机器模式中不允许。 
  2. 与异常相关的异常 
  E X C E P T I O N _ I N VA L I D _ D I S P O S I T I O N。一个异常过滤器返回一值,这个值不是E X C E P T I O N _ E X E C U T E _ H A N D L E R 、E X C E P T I O N _ C O N T I N U E _ S E A R C H、E X C E P T I O N _ C O N T I N U E _ E X E C U T I O N三者之一。 
  E X C E P T I O N _ N O N C O N T I N U A B L E _ E X C E P T I O N。一个异常过滤器对一个不能继续的异常返回E X C E P T I O N _ C O N T I N U E _ E X E C U T I O N。 
  3. 与调试有关的异常 
  EXCEPTION_BREAKPOINT。遇到一个断点。 
  E X C E P T I O N _ S I N G L E _ S T E P。一个跟踪陷井或其他单步指令机制告知一个指令已执行完毕。 
  E X C E P T I O N _ I N VA L I D _ H A N D L E。向一个函数传递了一个无效句柄。 
  4. 与整数有关的异常 
  EXCEPTION_INT_DIVIDE_BY_ZERO。线程试图用整数0来除一个整数 
  EXCEPTION_INT_OVERFLOW。一个整数操作的结果超过了整数值规定的范围。 
  5. 与浮点数有关的异常 
  E X C E P T I O N _ F LT _ D E N O R M A L _ O P E R A N D。浮点操作中的一个操作数不正常。不正常的值是一个太小的值,不能表示标准的浮点值。 
  EXCEPTION_FLT _ D I V I D E _ B Y _ Z E R O。线程试图用浮点数0来除一个浮点。 
  EXCEPTION_FLT _ I N E X A C T _ R E S U LT。浮点操作的结果不能精确表示成十进制小数。 
  EXCEPTION_FLT _ I N VA L I D _ O P E R AT I O N。表示任何没有在此列出的其他浮点数异常。 
  EXCEPTION_FLT _ O V E R F L O W。浮点操作的结果超过了允许的值。 
  EXCEPTION_FLT _ S TA C K _ C H E C K。由于浮点操作造成栈溢出或下溢。 
  EXCEPTION_FLT _ U N D E R F L O W。浮点操作的结果小于允许的值。 
  函数GetExceptionCode只能在一个过滤器中调用(__except之后的括号里),或在一个异常处理程序中被调用。记住,不能在一个异常过滤器函数里面调用GetExceptionCode。编译程序会捕捉这样的错误。 
  还有,上面的异常代码遵循在WinError.h文件中定义的有关错误代码的规则。(捎后我会写一段小的文章表明WinError.h的作用) 
  GetExceptionInformation 
  当一个异常发生时,操作系统要向引起异常的线程的栈里压入三个结构,这三个结构是:EXCEPTION_RECORD结构、CONTEXT结构和EXCEPTION_POINTERS结构。 
  EXCEPTION_RECORD结构包含有关已发生异常的独立于C P U的信息, 
  CONTEXT结构包含已发生异常的依赖于C P U的信息。 
  EXCEPTION_POINTERS结构只有两个数据成员,二者都是指针,分别指向被压入栈的EXCEPTION_POINTERS和CONTEXT结构。 
  为了取得这些信息并在你自己的程序中使用这些信息,需要调用GetExceptionInformation 
  函数:这个内部函数返回一个指向EXCEPTION_POINTERS结构的指针。 
  关于GetExceptionInformation函数,要记住的最重要事情是它只能在异常过滤器中调用,因为仅仅在处理异常过滤器时, EXCEPTION_RECORD和EXCEPTION_POINTERS才是有效的。一旦控制被转移到异常处理程序,栈中的数据就被删除。 
  如果需要在你的异常处理程序块里面存取这些异常信息(虽然很少有必要这样做),必须将EXCEPTION_POINTERS结构所指向的CONTEXT数据结构和/或EXCEPTION_RECORD数据结构保存在你所建立的一个或多个变量里。下面的代码说明了如何保存EXCEPTION_RECORD和CONTEXT数据结构: 
  void Func_SEHExceptionGetInfo() 
  { 
  EXCEPTION_RECORD SaveExceptRec; 
  CONTEXT SaveExceptContext; 
  int x = 0; 
  __try{ 
  x = 5/x; 
  } 
  __except(SaveExceptRec = 
  *(GetExceptionInformation())->ExceptionRecord, 
  SaveExceptContext = 
  *(GetExceptionInformation())->ContextRecord, 
  EXCEPTION_EXECUTE_HANDLER 
  ) 
  { 
  switch(SaveExceptRec.ExceptionCode) 
  { 
  file://Here, Do your thing for code value 
  } 
  } 
  } 
  上面的代码中:注意在异常过滤器中C语言逗号(,)操作符的使用。许多程序员不习惯使用这个操作符。它告诉编译程序从左到右执行以逗号分隔的各表达式。当所有的表达式被求值之后,返回最后的(或最右的)表达式的结果。 
  下面是EXCEPTION_RECORD的结构: 
  typedef struct _EXCEPTION_RECORD { 
  DWORD ExceptionCode; 
  DWORD ExceptionFlags; 
  struct _EXCEPTION_RECORD *ExceptionRecord; 
  PVOID ExceptionAddress; 
  DWORD NumberParameters; 
  DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS] ; 
  } EXCEPTION_RECORD; 
  EXCEPTION_RECORD结构包含有关最近发生的异常的详细信息,这些信息独立于C P U: 
  ExceptionCode包含异常的代码。这同内部函数GetExceptionCode返回的信息是一样的。 
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/njuitjf/archive/2009/03/27/40 29964.aspx
  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_POIN TERS 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_PO INTERS 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(GetExce ptionInformation()))
  {
  //
  }
  __try
  {
  // guarded code
  }
  __exceptexception_int_divide_by_zero_filter(GetExc eptionInformation()))
  {
  //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核心编程。不过还是建议你看英文原版,翻译的版本质量不高。
分享到:
评论

相关推荐

    Spring Cloud Gateway的全局异常处理

    Spring Cloud Gateway的全局异常处理 Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求。 网关都是给接口做...

    C#异常处理总结及简单实例

    C#异常处理总结及简单实例 一、异常处理的理解? 异常处理是指程序在运行过程中,发生错误会导致程序退出,这种错误,就叫做异常。 因此处理这种错误,就称为异常处理。 二、异常处理如何操作? C# 异常处理时建立在...

    异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt

    异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt

    两数计算+异常处理

    课程作业,实现两数计算及其异常处理,异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。 Java中的异常可以是函数...

    精讲RestTemplate自定义请求失败异常处理.docx

    在开始进行自定义的异常处理逻辑之前,我们有必要看一下异常处理的默认实现。也就是:为什么会产生上面小节提到的现象? ResponseErrorHandler是RestTemplate请求结果的异常处理器接口 o接口的第一个方法hasError...

    异常处理 异常处理 异常处理

    关于异常处理的word文档 关于异常处理的word文档 关于异常处理的word文档

    Springboot全局异常处理demo.zip

    Springboot全局异常处理demo 项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的...

    MySQL定义异常和异常处理详解

    主要为大家详细介绍了MySQL定义异常和异常处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    C和C++中的异常处理

    2. Microsoft 对异常处理方法的扩展 3. 标准 C++异常处理的基本语法和语义 4. 实例剖析 EH 5. C++的 new 和 delete 操作时的异常处理 6. Microsoft 对于的实现版本中的异常处理 7. 部分构造及 placement delete 8. ...

    C++ 异常处理 C++ 异常处理

    C++ 异常处理 C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理

    java异常处理java异常处理

    java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理

    c/vc++/MFC异常处理/结构化异常处理 浅析

    c/vc++/结构化异常处理 浅析 C语言异常处理 C++语言异常处理 异常处理函数 MFC异常处理 结构化异常处理

    spingmvc+mybatis+统一异常处理机制

    统一异常处理会区分前端是否ajax请求,自动返回json数据格式,要求开发人员在处理ajax请求时统一封装成一个对象返回,以符合代码统一规范。 此工程在idea环境编写,导入请自己新建工程手工复制代码导入。

    易语言线程结构异常处理

    易语言线程结构异常处理源码,线程结构异常处理,SE保护内存读写,除0异常,十到十六,到十六进制文本,汇编_写到内存,指针到EXCEPTION_RECORD结构,指针到CONTEXT结构

    ADS异常处理.pptADS异常处理.pptADS异常处理.ppt

    ADS异常处理.pptADS异常处理.pptADS异常处理.ppt

    ARM异常处理机制ARM异常处理机制

    ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制

    详解SpringCloud Finchley Gateway 统一异常处理

    主要介绍了详解SpringCloud Finchley Gateway 统一异常处理,非常具有实用价值,需要的朋友可以参考下

    工作流系统异常处理实现方法

    中的异常处理问题显得尤为突出[1-3]。传统上将异常处理包含于正常流程中的方法不仅不能 有效的处理各类异常,同时使得整个系统流程复杂化;而完全的人工参与也使得异常处理过 程效率低下,形式极不规范。所以,工作...

    第7章 java异常处理

    第7章 java异常处理

    SQLserver存储过程异常处理.txt

    SQLserver存储过程异常处理

Global site tag (gtag.js) - Google Analytics