马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 无符号整形 于 2016-7-4 21:41 编辑
上次说好了要交大家如何私底下处理异常,今天就教。在这篇文章结束时,我会和大家一起讨论如何改编错误的strcat程序。
今天主要讲:
1.__except标识符
2.EXCEPTION_EXECUTE_HANDLER
3.EXCEPTION_CONTINUE_EXECUTION
4.EXCEPTION_CONTINUE_SEARCH
5.升级版的strcat程序
好的,让我们进入正题吧!
1.__except标识符:
__except是一种标识符,当__try块在执行时抛出了异常(注意:它不会像finally块那样不让你退出)就会被执行,它比finally块稍微复杂一点点。因为windows要求__except块必须返回一个值,而且具体返回几是有要求的。
标识符格式:__try
{
//你认为很容易出错的代码
}
__except(/*处理的返回值,也可以理解成我们要求操作系统处理的方式*/)
{
//异常处理程序
}
注意__except关键字,任何时候创建一个__try块,后面必须跟着一个__finally块或者__except块。但是try块后面不能同时有__finally块和__except块也不能有多个__finally块或__except块。但是他们互相可以嵌套
至于后面得参数就留到后面去解释啦!
2.EXCEPTION_EXECUTE_HANDLER
这个标识符用来决定except的处理方式
EXCEPTION_EXECUTE_HANDLER就等于告诉操作系统:“我知道这个错误(错误),并预计这个异常在某种情况下会发生,同时已经写了一些代码去来处理它,让这些代码现在就执行吧!“注意:这个是__except块后面跟的那个括号了面的值,在excpt.h中被定义为1。
EXCEPTION_EXECUTE_HANDLER的使用方法:__try
{
//你认为很容易出错的__代码
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//异常处理程序
}
好了,让我们试着改编上次的strcat程序吧!
上次的代码:#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
int main()
{
__try{
strcat(NULL, NULL);
}
__finally{
MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
}
return 0;
}
这次我们直接把__finally换成__except(EXCEPTION_EXECUTE_HANDLER),表示系统发现错误后立即执行__except'
也就是这样#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
int main()
{
__try{
strcat(NULL, NULL);
}
__except (EXCEPTION_EXECUTE_HANDLER){
MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
}
return 0;
}
编译并运行,这下子不会弹出“xxx.exe已停止工作“的对话框了。嘿嘿,倒是弹出下面的对话框
耶!我们终于可以利用SEH私底下处理错误了!太好了!
这就说明了EXCEPTION_EXECUTE_HANDLER的含义,大家看完之后记得敲代码试试哦!
3.EXCEPTION_CONTINUE_EXECUTION
这个嘛,就是让系统吧出错的语句再执行一次,一般都会导致再次发生错误,然后再次执行而死循环!
不过在某些地方,还是有用的。
下面的代码摘自《Windows核心编程》:TCHAR g_szBuffer[100];
void FunclinRoosevelt1() {
int x = 0;
TCHAR *pchBuffer = NULL;
__try {
*pchBuffer = TEXT('J');
X = 5 / X;
}
__except(OilFilter1(&pchBuffer) ) {
MessageBox(NULL, TEXT("An exception occurred") , NULL , MB_OK);
}
MessageBox(NULL, TEXT("Function"), NULL, MB_OK);
}
LONG OilFilrer1(TCHAR **ppchBuffer) {
if(*ppchBuffer == NULL){
*ppchBuffer = g_szBuffer;
return (EXCEPTION_CONTIUE_EXECUTION);
}
return(EXCEPTION_EXECUTE_HANDLER);
}
《Windows核心编程》的解释如下
当函数将字符'J'至置于pchBuffer所指向的内存缓冲区内是,遇到了第一个问题:很不辛,我们没有初始化pchBuffer,让他指向全局内存缓冲区g_szBuffer。因此,pchBuffer的值为NULL.。CPU会抛出一个异常,并对发生异常的__try块所对应的__except块的异常过滤程序进行求值。后者则以变量pchBuffer作为参数值调用OilFilter1。
当OilFilter1开始执行,它首先检查**ppchBuffer的值是是不是NULL,如果是,设置**ppBuffer的值,让他指向全局内存缓冲g_szBuffer。预算这次异常处理返回结果为EXCEPTION_CONTIUE_EXECUTION。系统·在看到过滤程序的返回职为EXCEPTION_CONTIUE_EXECUTION后,将程序控制控制流跳转到导致异常的那条指令,并尝试再次执行这条指令。这次,指令执行成功,'J'被置于g_szBuffer所指向缓冲区的第一个字节。
代码继续执行,将会遇到0作为除数的异常。系统再一次计算异常过滤程序表达式。这一次,OilFilter检查到**ppchBuffer的值不是NULL,于是返回EXCEPTION_EXECUTE_HANDLER,让系统执行except代码块。于是一个消息框被弹出,指明一个错误发生。
4.EXCPTION_CONTIUE_SEARCH
这个就是让系统执行上次的__try块,一般很少用,了解即可。
实例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
int main()
{
__try{
strcat(NULL, NULL);
}
__except (EXCEPTION_CONTINUE_SEARCH){
MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
}
MessageBox(NULL, "我还好呢!", "提醒", MB_OK | MB_ICONEXCLAMATION);
return 0;
}
你猜会如何?就是延迟一会就停止工作
5.升级版strcat程序
我直接上代码看看大家看不看得懂
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
int main()
{
__try{
strcat(NULL, NULL);
}
__except (EXCEPTION_EXECUTE_HANDLER){
MessageBox(NULL, "拼接异常!", "错误", MB_OK | MB_ICONERROR);
}
MessageBox(NULL, "我还好呢!", "提醒", MB_OK | MB_ICONEXCLAMATION);
MessageBox(NULL, "拼接结果:NULLNULL", "结果出来了!", MB_OK | MB_ICONINFORMATION);
return 0;
}
运行结果:
其他的就要你自己总结了哟! |