马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 无符号整形 于 2016-7-3 17:10 编辑
相信大家刚学C的时候都会因为粗心写出类似于这样的代码:#include<stdio.h>
int main()
{
int i;
scanf("%d",i);
return 0;
}
会怎样?
时间久了,就不会那么粗心了。不过,你真的了解“停止工作”的意义吗?
那就是SEH!
结构化异常处理(struct exception handing,SEH)简单来说,就是可以在系统在想用户报告错误之前能让程序私底下处理错误的系统。
SEH是什么?他有什么用?
他用处太大了!如果你想一想:有足够的内存、没有非法的指针,要访问的文件始终存在……如果你觉得这是一个梦的话呢,你一定就会爱上SEH。SEH带来的好处是我们可以先集中精力来完成软件的正常行为。如果出现了问题,系统就会通知我们。
不过,不同编译器这对SEH的实现不尽相同,所以建议使用微软编译器
SEH实际上包含两个功能:终止处理和异常处理。这一次讨论终止处理,下一次才讨论异常处理。
好啦,然我们开始第一个SEH程序吧!
1.改进前的Fun1函数:DWORD Fun1()
{
······
Wait ForSingleObject(g_hsm,INFINITE);
d_Data = 0;
return d_Data;
ReleaseSemaphore(g_hsm,1,NULL);
}
这里有一个严重的问题:程序等待一个信号量(关键段)的控制权,它成功获取控制权后,因为释放信号量的语句在return的后面,所以后面得释放信号量(关键段)的语句永远不会被执行!既然占用了不释放,其他等待这个信号量线程再也无法执行(发生了死锁),这样的顺序照成了非常严重的问题。
当然,使用SEH可以很好的解决这个大问题。
改进后的Fun1函数:DWORD Fun1()
{
······
__try
{
Wait ForSingleObject(g_hsm,INFINITE);
d_Data = 0;
return d_Data;
}
__finally
{
ReleaseSemaphore(g_hsm,1,NULL);
}
{
当return语句执行的时候试图退出try块的时候,编译器会让__finally块在他之前执行。信号量得到了释放,这个问题也就迎刃而解了。
下面这个例子,终止处理将真正证明他的价值
2.改进前的程序#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
int main()
{
strcat(NULL, NULL);
MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
return 0;
}
这个函数的问题是strcat穿进去NULL将会导致异常!
让我们尝试着运行此程序
然后就。。。
为了让我们的程序正常运行,我们把她加上__try块!#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;
}
运行一下它
然后我们点击取消按钮,“神奇”的一幕发生了……
什么?我们的程序检测到了停止工作!?
没错!这就证明了一句话:
这是因为SEH在工作!
总结:__try块和__finally块的原理
1.程序执行到__try块
2.如果在执行__try块时,程序发生了异常,或者尝试跳出__try块的话,就会被强迫执行__finally块
3.执行前WER会把情况报告给用户,然后在执行__finally块
但是,我们还没实现私底下处理。下次“未处理异常 2. 异常处理程序”可能会讲到哟~
8888888888888888888888 |