鱼C论坛

 找回密码
 立即注册
查看: 2207|回复: 0

[技术交流] 未处理异常 1.SEH是什么 终止处理程序

[复制链接]
发表于 2016-7-3 17:03:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 无符号整形 于 2016-7-3 17:10 编辑

相信大家刚学C的时候都会因为粗心写出类似于这样的代码:
  1. #include<stdio.h>
  2. int main()
  3. {
  4.         int i;
  5.         scanf("%d",i);
  6.         return 0;
  7. }
复制代码

会怎样?
停止工作.JPG
时间久了,就不会那么粗心了。不过,你真的了解“停止工作”的意义吗?
那就是SEH
结构化异常处理(struct exception handing,SEH)简单来说,就是可以在系统在想用户报告错误之前能让程序私底下处理错误的系统。
SEH是什么?他有什么用?
他用处太大了!如果你想一想:有足够的内存、没有非法的指针,要访问的文件始终存在……如果你觉得这是一个梦的话呢,你一定就会爱上SEH。SEH带来的好处是我们可以先集中精力来完成软件的正常行为。如果出现了问题,系统就会通知我们。

不过,不同编译器这对SEH的实现不尽相同,所以建议使用微软编译器
SEH实际上包含两个功能:终止处理和异常处理。这一次讨论终止处理,下一次才讨论异常处理。
好啦,然我们开始第一个SEH程序吧!
1.改进前的Fun1函数:
  1. DWORD Fun1()
  2. {
  3.         ······
  4.         Wait        ForSingleObject(g_hsm,INFINITE);
  5.          d_Data = 0;
  6.         return d_Data;
  7.         ReleaseSemaphore(g_hsm,1,NULL);       
  8. }
复制代码

这里有一个严重的问题:程序等待一个信号量(关键段)的控制权,它成功获取控制权后,因为释放信号量的语句在return的后面,所以后面得释放信号量(关键段)的语句永远不会被执行!既然占用了不释放,其他等待这个信号量线程再也无法执行(发生了死锁),这样的顺序照成了非常严重的问题。
当然,使用SEH可以很好的解决这个大问题。
改进后的Fun1函数:
  1. DWORD Fun1()
  2. {
  3.         ······
  4.         __try
  5.         {
  6.                 Wait        ForSingleObject(g_hsm,INFINITE);
  7.                  d_Data = 0;
  8.                 return d_Data;
  9.         }
  10.         __finally
  11.         {
  12.                 ReleaseSemaphore(g_hsm,1,NULL);       
  13.         }
  14. {
复制代码

当return语句执行的时候试图退出try块的时候,编译器会让__finally块在他之前执行。信号量得到了释放,这个问题也就迎刃而解了。
下面这个例子,终止处理将真正证明他的价值
2.改进前的程序
  1. #define _CRT_SECURE_NO_WARNINGS

  2. #include<stdio.h>
  3. #include<windows.h>
  4. int main()
  5. {
  6.        
  7.         strcat(NULL, NULL);
  8.         MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
  9.         return 0;
  10. }
复制代码

这个函数的问题是strcat穿进去NULL将会导致异常!
让我们尝试着运行此程序
123a.JPG
然后就。。。
为了让我们的程序正常运行,我们把她加上__try块!
  1. #define _CRT_SECURE_NO_WARNINGS

  2. #include<stdio.h>
  3. #include<windows.h>
  4. int main()
  5. {
  6.         __try{
  7.                 strcat(NULL, NULL);
  8.         }
  9.         __finally{
  10.                 MessageBox(NULL, "发生了未处理异常!", "错误", MB_OK | MB_ICONERROR);
  11.         }
  12.         return 0;
  13. }
复制代码

运行一下它
656.JPG
然后我们点击取消按钮,“神奇”的一幕发生了……
4t.JPG
什么?我们的程序检测到了停止工作!?
没错!这就证明了一句话:
这是因为SEH在工作!





总结:__try块和__finally块的原理
1.程序执行到__try块
2.如果在执行__try块时,程序发生了异常,或者尝试跳出__try块的话,就会被强迫执行__finally块
3.执行前WER会把情况报告给用户,然后在执行__finally块

但是,我们还没实现私底下处理。下次“未处理异常 2. 异常处理程序”可能会讲到哟~

8888888888888888888888

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 08:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表