原文地址:http://blog.csdn.net/starlee/article/details/6636723

SEH的全称是Structured Exception Handling,是Windows操作系统提供的一种异常处理方式。SEH是属于操作系统的特性,不为特定语言设计,从它的名字就能看出它是一种结构化的异常处理方式。SEH包括了2个部分:终止处理__try/__finally和异常处理__try/__except,下面分别进行介绍。

终止处理__try/__finally
        __try/__finally可以保证无论try块内的代码执行结果如何,finally块内的代码总会被调用和执行。现在用下面的这个VC++中的控制台程序来说明。

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. __try
  4. {
  5. MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);
  6. // 除零,人为的使程序崩溃
  7. //
  8. int i = 13;
  9. int j = 0;
  10. int m = i / j;
  11. }
  12. __finally
  13. {
  14. // 在这里添加处理程序崩溃情况的代码
  15. //
  16. // 这里以弹出一个对话框为例子
  17. //
  18. MessageBox(NULL, _T("Message from '__finally' section"), _T("Test"), MB_OK);
  19. }
  20. MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);
  21. return 0;
  22. }

编译上面的代码。运行生成的EXE,会弹出下面的对话框。

点击OK按钮后,程序会崩溃。

在出现上面这个对话框的时候点击Cancel,将控制权返还给程序,那么下面的对话框就会弹出。

点击OK按钮后,程序正常退出。
        由上面的例子可以看出,无论try块中的代码会不会出现异常,在程序终止的时候,finally块中的代码都会被调用和执行。所以一般情况下,finally块中的代码都是用来做一些清理工作和资源的释放。

异常处理__try/__except
        __try/__except是用来捕捉异常的,只有当try块中的代码出现异常的时候,except块中的代码才会被调用和执行。它的语法是这样的:

  1. __try
  2. {
  3. // guarded code
  4. }
  5. __except(expression)
  6. {
  7. // exception handler code
  8. }

它最大的一个好处就是可以完全控制异常进程。expression的值决定了异常被处理完后,进程该如何执行。下面依然用VC++中的控制台程序来说明。

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. __try
  4. {
  5. MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);
  6. // 除零,人为的使程序崩溃
  7. //
  8. int i = 13;
  9. int j = 0;
  10. int m = i / j;
  11. }
  12. __except(EXCEPTION_EXECUTE_HANDLER)
  13. {
  14. // 在这里添加处理程序崩溃情况的代码
  15. //
  16. // 这里以弹出一个对话框为例子
  17. //
  18. MessageBox(NULL, _T("Message from '__except' section"), _T("Test"), MB_OK);
  19. }
  20. MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);
  21. return 0;
  22. }

编译上面的代码。运行生成的EXE,会依次弹出下面的对话框。

可以看出,在异常处理代码被调用执行后(except块中的代码),程序继续可以继续运行,并正常退出,并没有崩溃!通过使用__try/__except可以捕捉到任何类型的异常,并保证程序不会崩溃!(想想这是多么的神奇,一个程序永远不会崩溃!)
        下面解释一下except中表达式各个值的含义:

EXCEPTION_CONTINUE_SEARCH        异常没有被处理,继续向上抛出。如果更上层的代码没有异常捕捉机制,程序就会崩溃。
EXCEPTION_CONTINUE_EXECUTION   异常已经被处理,返回异常发生的地方继续执行。
EXCEPTION_EXECUTE_HANDLER        异常已经被处理,程序继续往后执行。

通过上面的例子可以知道,SEH的异常处理跟C++的异常处理不同,C++的try/catch不能控制异常进程,对于异常,要么处理,要么继续向上抛出。而SEH却能完全控制异常进程,处理完异常之后,还能决定进该进程如何执行。只要SEH运用得当,编写一个永不崩溃的应用程序成为可能。但是SEH有一个致命的弱点,那就是它是一种结构化的异常处理,所以不支持面向对象。下面用具体的VC++控制台程序来说明。

  1. // 一个有函数调用的类
  2. //
  3. class CrashTest
  4. {
  5. public:
  6. CrashTest() {}
  7. ~CrashTest() {}
  8. void Test()
  9. {
  10. Crash();
  11. }
  12. private:
  13. void Crash()
  14. {
  15. // 除零,人为的使程序崩溃
  16. //
  17. int i = 13;
  18. int j = 0;
  19. int m = i / j;
  20. }
  21. };
  22. int _tmain(int argc, _TCHAR* argv[])
  23. {
  24. __try
  25. {
  26. CrashTest test;
  27. test.Test();
  28. }
  29. __except(EXCEPTION_EXECUTE_HANDLER)
  30. {
  31. // 在这里添加处理程序崩溃情况的代码
  32. //
  33. }
  34. return 0;
  35. }

上面的代码不能通过编译,VC++编译器会给出这样的错误信息:error C2712: Cannot use __try in functions that require object unwinding。错误原因很简单,try块内使用了对象。
        要想解决这个问题,可以把使用对象的逻辑放到一个函数里,然后在try里调用这个函数,来骗过编译器。把上面的代码修改成下面这样就可以通过编译。

    1. void Test()
    2. {
    3. CrashTest test;
    4. test.Test();
    5. }
    6. int _tmain(int argc, _TCHAR* argv[])
    7. {
    8. __try
    9. {
    10. Test();
    11. }
    12. __except(EXCEPTION_EXECUTE_HANDLER)
    13. {
    14. // 在这里添加处理程序崩溃情况的代码
    15. //
    16. }
    17. return 0;
    18. }

[转]让程序在崩溃时体面的退出之SEH的更多相关文章

  1. [转]让程序在崩溃时体面的退出之SEH+Dump文件

    原文地址:http://blog.csdn.net/starlee/article/details/6649605 在我上篇文章<让程序在崩溃时体面的退出之SEH>中讲解了SEH中try/ ...

  2. [转]让程序在崩溃时体面的退出之Dump文件

    原文地址:http://blog.csdn.net/starlee/article/details/6630816 在我的那篇<让程序在崩溃时体面的退出之CallStack>中提供了一个在 ...

  3. [转]让程序在崩溃时体面的退出之CallStack

    原文地址:http://blog.csdn.net/starlee/article/details/6618849 在我的那篇<让程序在崩溃时体面的退出之Unhandled Exception& ...

  4. 让程序在崩溃时体面的退出之Dump文件

             在我的那篇<让程序在崩溃时体面的退出之CallStack>中提供了一个在程序崩溃时得到CallStack的方法.但是要想得到CallStack,必须有pdb文件的支持.但 ...

  5. [转]让程序在崩溃时体面的退出之Unhandled Exception

    原文地址:http://blog.csdn.net/starlee/article/details/6613424 程序是由代码编译出来的,而代码是由人写的.人非圣贤,孰能无过.所以由人写的代码有缺陷 ...

  6. 编写的windows程序,崩溃时产生crash dump文件的办法

    一.引言 dump文件是C++程序发生异常时,保存当时程序运行状态的文件,是调试异常程序重要的方法,所以程序崩溃时,除了日志文件,dump文件便成了我们查找错误的最后一根救命的稻草.windows程序 ...

  7. android在程序崩溃时Catch异常并处理

    Android系统的"程序异常退出",给应用的用户体验造成不良影响.为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理.通过Th ...

  8. 让linux中的程序崩溃时生成core文件

    当我们的linux程序崩溃的时候,常常会有这样的提示:    Segmentation fault (core dumped)    段错误 (核心已转储)    提示说生成了core文件,但是此功能 ...

  9. 使用SetUnhandledExceptionFilter转储程序崩溃时内存DMP .

    关于程序崩溃时转储内存DMP,可以设置注册表,使程序崩溃时自动转储内存DMP,见程序崩溃时利用注册表自动转储内存DMP.本文要介绍的是使用SetUnhandledExceptionFilter函数在程 ...

随机推荐

  1. 设置透明navigationBar

    三行代码轻松实现透明navigationBar:  [self.navigationController.navigationBar setBackgroundImage:[UIImage new] ...

  2. C# 反射 表达式树 模糊搜索

    反射实体T,非datetime字段反射获取表达式树   public static Expression<Func<T, bool>> GetSearchExpression& ...

  3. Ext.Array 方法

    1. Ext.Array.clean(arr); 过滤数组中的空元素 var arr = [1,"",2,"",3]; Ext.clean(arr); // [ ...

  4. [转]IoC框架

    1 IoC理论的背景     我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑.   图1:软件系统中耦合的对象 如果 ...

  5. uboot环境变量区为何不能放在data段

    一.疑问 环境变量也是全局变量,为何不能像其他的全局变量放在data段呢?为什么要放在堆中或者使用ENV_IS_EMBEDDED定义的CFG_ENV_SIZE的空间大小,又为什么需要这么大的空间呢? ...

  6. JSP 结构

    网络服务器需要一个JSP引擎,也就是一个容器来处理JSP页面. 容器负责截获对JSP页面的请求.本教程使用内嵌JSP容器的Apache来支持JSP开发. JSP容器与Web服务器协同合作,为JSP的正 ...

  7. Java-反射再学习

    反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类. packa ...

  8. "_OBJC_CLASS_$_WeiboApi", referenced from: objc-class-ref in libtuyoo.a(TuYoo.o)

    Undefined symbols for architecture i386: "_OBJC_CLASS_$_WeiboApi", referenced from: objc-c ...

  9. Loading CSS without blocking render

    The principles behind these techniques aren't new. Filament group, for example, have published great ...

  10. 上网必备AdBlock,远离广告!

    浏览器广告拦截插件,绝对上网必备... 从此告别讨厌的百度边栏广告!!! https://getadblock.com/ https://adblockplus.org/zh_CN/