windows核心编程---异常处理程序与软件异常

来源:互联网 发布:mac散热口在哪 编辑:程序博客网 时间:2024/06/04 23:05

CPU抛出的异常是硬件异常,操作系统和应用程序抛出的异常是软件异常。

硬件或软件异常被抛出时,可用:

__try{}__except(exception filter// 异常过滤程序){// 异常处理程序}

一个__try后,只需跟一个__except或__finally(终止处理程序)。

-异常过滤程序,异常处理程序
异常过滤程序,异常处理程序
主要有系统实现。

只在__try块中发生异常,才会转入__except,__try块未发生异常,不会进入__except块。

异常过滤表达式的值必定为以下三个标识符之一:
EXCEPTION_EXECUTE_HANDLER// 执行__except块中代码
EXCEPTION_CONTINUE_SEARCH// 到上一层__try中寻找异常处理方法
EXCEPTION_CONTINUE_EXECUTION// 忽略异常,继续执行

-EXCEPTION_EXECUTE_HANDLE
执行异常处理块中代码。
执行__except代码块,执行结束,继续往下从__except块后执行。

void FuncOStimpy1(){// 1__try{// 2FuncORen1();}__except(/6/EXCEPTION_EXECUTE_HANDLER){// 8MessageBox(...);}// 9}void FuncORen1(){DWORD dwTemp = 0;// 3__try{// 4WaitForSingleObject(g_hSem, INFINITE);// 5g_dwProtectedData = 5 / dwTemp;}__finally{// 7 // 若在这里直接return,异常处理的89不会被执行。相当于本函数正常返回。try/except下多级try/finally类似。ReleaseSemaphore(g_hSem, 1, NULL);}}

-EXCEPTION_CONTINUE_EXECUTION

TCHAR g_szBuffer[100];void FunclinRoosevelt1(){int x = 0;TCHAR *pchBuffer = NULL;__try{*pchBuffer = TEXT('J');x = 5 / x;}__except(/*异常过滤程序,返回值必须为3个异常常量中一个*/OilFilter1(&pchBuffer)){MessageBox(NULL,TEXT("An exception occurred"),NULL,MB_OK);}MessageBox(NULL,TEXT("Function completed"),NULL,MB_OK);}LONG OilFilter1(TCHAR **ppchBuffer){if(*ppchBuffer == NULL){*ppchBuffer = g_szBuffer;// 将控制流跳转到导致异常的那条指令,并尝试重新执行这条指令return EXCEPTION_CONTINUE_EXECUTION;}// 让系统执行except代码块return EXCEPTION_EXECUTE_HANDLER;}

-EXCEPTION_CONTINUE_SEARCH
继续往上层try搜索except.

-GetExceptionCode

__try{x=0;y=4 / x;...}__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO)? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH){}// 表明刚刚发生的异常的类型DWORD GetExceptionCode();

// 内存相关异常
EXCEPTION_ACCESS_VIOLATION 写一个错误的虚拟地址
EXCEPTION_DATATYPE_MISALIGNMENT 线程试图从没有提供自动对齐机制的硬件里读入没有对齐的数据。
EXCEPTION_ARRAY_BOUNDS_EXCEEDED 线程在支持边界检查的硬件上访问越界的数组元素。
EXCEPTION_IN_PAGE_ERROR 文件系统或设备取得读取错误而引起的页错误。
EXCEPTION_GUARD_PAGE 线程试图访问具备PAGE_GUARD属性内存页。
EXCEPTION_STACK_OVERFLOW 线程用光栈空间
EXCECPTION_ILLEGAL_INSTRUCTION 非法指令
EXCEPTION_PRIV_INSTRUCTION 试图执行当前机器模式下不允许的操作

// 与异常本身相关的异常
EXCEPTION_INVALID_DISPOSITION 异常过滤返回3个常量以外值
EXCEPTION_NONCONTINUABLE_EXCEPTION 异常过滤返回继续执行,但实际这类异常不能继续

// 与调试相关异常
EXCEPTION_BREAKPOINT 执行到断点
EXCEPTION_SINGLE_STEP 单步
EXCEPTION_INVALID_HANDLE 传入无效句柄给一函数

// 与整型相关的异常
EXCEPTION_INT_DIVIDE_BY_ZERO 线程试图在整数除法运算中以0做除数
EXCEPTION_INT_OVERFLOW 整型运算结果超出范围

// 与浮点类型相关的异常
EXCEPTION_FLT_DENORMAL_OPERAND 浮点运算中一个运算数是不能作为标准浮点数的小数。
EXCEPTION_FLT_DIVIDE_BY_ZERO 线程试图在浮点除法中以0做除数
EXCEPTION_FLT_INEXACT_RESULT 浮点运算结果不能精确地表示为十进制小数
EXCEPTION_FLT_INVALID_OPERATION 其它浮点数异常
EXCEPTION_FLT_OVERFLOW 浮点运算指数部分超出该类型允许的最大值
EXCEPTION_FLT_STACK_CHECK 浮点运算造成栈上溢出或下溢出
EXCEPTION_FLT_UNDERFLOW 浮点运算指数部分小于该类型允许的最小值

GetExceptionCode只能用在异常过滤程序里(仅限与__except后的括号里),或异常处理程序里。

异常代码遵循WinError.h中有关错误代码的规则

-GetExceptionInformation
一个异常发生时,系统将向发生异常的线程的栈中压入3个结构,
// 包含关于抛出异常的信息
EXCEPTION_RECORD,
// 与异常和CPU相关的信息
CONTEXT,
// 含两个指针,指向前两个结构
EXCEPTION_POINTERS。

PEXCEPTION_POINTERS GetExceptionInformation();

这个函数只能在异常过滤程序中调用,因为上述3个结构只在系统计算异常过滤程序时才有效。
仅仅限与_except后的括号里。

typedef struct _EXCEPTION_RECORD{// 异常码DWORD ExceptionCode;// 异常标志DWORD ExceptionFlags;// 异常链struct _EXCEPTION_RECORD *ExceptionRecord;// 导致异常的CPU指令地址PVOID ExceptionAddress;// 异常相关参数个数DWORD NumberParameters;// 描述异常的附加数组ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];}EXCEPTION_RECORD;

对异常EXCEPTION_ACCESS_VIOLATION,
ExceptionInformation[0]:
0,读取不能访问的数据
1,写入不能访问的数据
8,执行不能访问的代码

__try{...}__except(ExpFltr(GetExceptionInformation())){...}LONG ExpFltr(LPEXCEPTION_POINTERS pep){TCHAR szBuf[300], *p;PEXCEPTION_RECORD pER = pep->ExceptionRecord;DWORD dwExceptionCode = pER->ExceptionCode;StringCchPrintf(szBuf,_countof(szBuf),TEXT("Code = %x, Address = %p"),dwExceptionCode,pER->ExceptionAddress);p = _tcschr(szBuf, TEXT('0'));switch(dwExceptionCode){case EXCEPTION_ACCESS_VIOLATION:    {        StringCchPrintf(        p,        _countof(szBuf),        TEXT("\n--> Attempt to %s data at address %p"),        pER->ExceptionInformation[0] ?        TEXT("write") : TEXT("read"),        pER->ExceptionInformation[1]        );    }    break;default:    break;}MessageBox(NULL,szBuf,TEXT("Exception"),MB_OK | MB_ICONEXCLAMATION);return EXCEPTION_CONTINUE_SEARCH;}

-软件异常
也可在应用代码抛出异常

// 抛出一个软件异常VOID RaiseException(// 要抛出异常标识符。// 如果定义自己的异常标识符,要遵循windows错误代码定义的标准格式。DWORD dwExceptionCode,// 标志:// 0// EXCEPTION_NONCONTINUABLE,此时异常过滤程序不能返回EXCEPTION_CONTINUE_EXECUTION.// 此时,过滤程序若返回EXCEPTION_CONTINUE_EXECUTION,会引发EXCEPTION_NONCONTINUABLE_EXCEPTIONDWORD dwExceptionFlags,// 异常附件信息DWORD nNumberOfArguments,// 异常附件信息CONST ULONG_PTR *pArguments);
阅读全文
0 0
原创粉丝点击