[转]C++异常处理 12

来源:互联网 发布:Extjs 数组去重 编辑:程序博客网 时间:2024/06/08 07:10

 下面的代码举例说明了一种方法,指出所发生异常的类别:
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返回的信息是一样的。

原创粉丝点击