- 浏览: 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核心编程。不过还是建议你看英文原版,翻译的版本质量不高。
发表评论
-
[原创]Google App Engine使用简介
2012-01-20 02:06 1030[原创]Google App Engine使用 ... -
Android:Debug certificate expired on DATE 解决方法
2012-01-20 02:06 901Android:Debug certificate expir ... -
使应用程序只能运行一个实例
2012-01-20 02:06 869使应用程序只能运行一个实例 2010年07月16日 这里 ... -
诺基亚手机里的秘密
2012-01-19 09:56 585诺基亚手机里的秘密 2011年05月18日 诺基亚手机* ... -
Windows XP系统文件一一诠释(1)[最新整理](转BY wang6610----BBS.WUYOU.COM)
2012-01-19 09:56 782Windows XP系统文件一一诠 ... -
5230
2012-01-19 09:56 5595230 2010年12月31日 一、购机后的头两件 ... -
sdsadsadas
2012-01-19 09:56 557sdsadsadas 2010年11月22日 XV67 ... -
5230
2012-01-19 09:56 6215230 2010年10月03日 1、屏幕保护:一定要买 ... -
ReleaseDC和DeleteDC的区别 (转)
2012-01-17 02:27 885ReleaseDC和DeleteDC的区别 (转) 2011 ... -
FlashBuilder4.5 下载 及破解方法
2012-01-17 02:27 718FlashBuilder4.5 下载 及破解方法 2011年 ... -
ROOT【个人学习,慎用】
2012-01-17 02:27 635ROOT【个人学习,慎用】 ... -
(转) iPhone UI 开发的几点建议
2012-01-17 02:27 532(转) iPhone UI 开发的几点 ... -
MFC自定义消息
2012-01-17 02:26 626MFC自定义消息 2011年11月28日 MFC自定义消 ... -
workplan
2012-01-15 22:12 406workplan 2011年04月18日 ... -
.net自定义控件小结进阶篇
2012-01-15 22:12 855.net自定义控件小结进阶篇 2010年12月14日 ... -
WPF中的控件
2012-01-15 22:12 1207WPF中的控件 2011年05月17日 1.Button ... -
【C#】在VS2005中C#实现鼠标悬停提示
2012-01-15 22:12 1482【C#】在VS2005中C#实现鼠标悬停提示 2010年01 ... -
flex ComboBox显示的字太长,用......代替
2012-01-15 22:12 1058flex ComboBox显示的字太长,用......代替 ...
相关推荐
Spring Cloud Gateway的全局异常处理 Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求。 网关都是给接口做...
C#异常处理总结及简单实例 一、异常处理的理解? 异常处理是指程序在运行过程中,发生错误会导致程序退出,这种错误,就叫做异常。 因此处理这种错误,就称为异常处理。 二、异常处理如何操作? C# 异常处理时建立在...
异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt异常处理.ppt
课程作业,实现两数计算及其异常处理,异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。 Java中的异常可以是函数...
在开始进行自定义的异常处理逻辑之前,我们有必要看一下异常处理的默认实现。也就是:为什么会产生上面小节提到的现象? ResponseErrorHandler是RestTemplate请求结果的异常处理器接口 o接口的第一个方法hasError...
关于异常处理的word文档 关于异常处理的word文档 关于异常处理的word文档
Springboot全局异常处理demo 项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的...
主要为大家详细介绍了MySQL定义异常和异常处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2. Microsoft 对异常处理方法的扩展 3. 标准 C++异常处理的基本语法和语义 4. 实例剖析 EH 5. C++的 new 和 delete 操作时的异常处理 6. Microsoft 对于的实现版本中的异常处理 7. 部分构造及 placement delete 8. ...
C++ 异常处理 C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理C++ 异常处理
java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理java异常处理
c/vc++/结构化异常处理 浅析 C语言异常处理 C++语言异常处理 异常处理函数 MFC异常处理 结构化异常处理
统一异常处理会区分前端是否ajax请求,自动返回json数据格式,要求开发人员在处理ajax请求时统一封装成一个对象返回,以符合代码统一规范。 此工程在idea环境编写,导入请自己新建工程手工复制代码导入。
易语言线程结构异常处理源码,线程结构异常处理,SE保护内存读写,除0异常,十到十六,到十六进制文本,汇编_写到内存,指针到EXCEPTION_RECORD结构,指针到CONTEXT结构
ADS异常处理.pptADS异常处理.pptADS异常处理.ppt
ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制ARM异常处理机制
主要介绍了详解SpringCloud Finchley Gateway 统一异常处理,非常具有实用价值,需要的朋友可以参考下
中的异常处理问题显得尤为突出[1-3]。传统上将异常处理包含于正常流程中的方法不仅不能 有效的处理各类异常,同时使得整个系统流程复杂化;而完全的人工参与也使得异常处理过 程效率低下,形式极不规范。所以,工作...
第7章 java异常处理
SQLserver存储过程异常处理