异常处理
- final型异常处理
- 线程相关的异常处理
传递给异常处理句柄的参数
异常处理的参数有四个:
- pExcept – EXCEPTIONN_RECORD结构的指针
- pErr – ERR结构的指针
- pContext – CONTEXT结构的指针
- pDispatch
1、 EXCEPTION_RECORD结构的定义
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode; //异常码
DWORD ExceptionFlags; //异常标志
struct _EXCEPTION_RECORD *ExceptionRecord; //指向另一个EXCEPTION_RECORD的指针
PVOID ExceptionAddress; //异常发生的地址
DWORD NumberParameters; //下面ExceptionInformation所含的数目
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; //附加消息
} EXCEPTION_RECORD;
经常遇到的ExceptionCode异常类型由:
- C0000005h – 读写内存冲突
- C0000094h – 非法除0
- C00000FDh – 堆栈溢出或越界
- 80000001h – 由Virtual Alloc建立起来的属性页冲突
- C0000025h – 不可持续一场,程序无法恢复执行,异常处理历程不应该处理这个异常
- C0000026h – 在异常处理过程中系统使用的代码,如果系统从某个历程莫名其妙的返回,则出现此代码。RtlUnWind时没有Exception Record参数也同样会填入这个代码
- 80000003h – 调试时因代码中int3中断
- 80000004h – 处于被单步调试状态
自己定义异常代码 规则:
ExceptionFlags异常标志:
- 0 – 可修复异常
- 1 – 不可修复
- 2 – 正在展开,不要试图修复什么,需要的话,释放必要的资源
堆栈展开
堆栈展开是异常处理例程在决定处理某个异常的时候,给前面不处理这个异常的处理例程一个清洗的机会,前面拒绝处理这个异常的历程可以释放必要的举兵对象或者释放堆栈或者做点其他的工作。
异常处理的几种情况
- 用来处理非致命错误的情况
- 对API函数的参数合法性的检验(假设参数都是合法的,只有与遇到异常的时候进行合法性校验)
- 处理致命错误(退出时最好的选择,但是有的时候可以用异常处理函数在程序退出前释放资源、删除临时文件等,甚至可以详细记录产生异常的指令位置和环境
- 处理“计划内”的异常