[转]让程序在崩溃时体面的退出之SEH
原文地址: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++中的控制台程序来说明。
- int _tmain(int argc, _TCHAR* argv[])
- {
- __try
- {
- MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);
- // 除零,人为的使程序崩溃
- //
- int i = 13;
- int j = 0;
- int m = i / j;
- }
- __finally
- {
- // 在这里添加处理程序崩溃情况的代码
- //
- // 这里以弹出一个对话框为例子
- //
- MessageBox(NULL, _T("Message from '__finally' section"), _T("Test"), MB_OK);
- }
- MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);
- return 0;
- }
编译上面的代码。运行生成的EXE,会弹出下面的对话框。
点击OK按钮后,程序会崩溃。
在出现上面这个对话框的时候点击Cancel,将控制权返还给程序,那么下面的对话框就会弹出。
点击OK按钮后,程序正常退出。
由上面的例子可以看出,无论try块中的代码会不会出现异常,在程序终止的时候,finally块中的代码都会被调用和执行。所以一般情况下,finally块中的代码都是用来做一些清理工作和资源的释放。
异常处理__try/__except
__try/__except是用来捕捉异常的,只有当try块中的代码出现异常的时候,except块中的代码才会被调用和执行。它的语法是这样的:
- __try
- {
- // guarded code
- }
- __except(expression)
- {
- // exception handler code
- }
它最大的一个好处就是可以完全控制异常进程。expression的值决定了异常被处理完后,进程该如何执行。下面依然用VC++中的控制台程序来说明。
- int _tmain(int argc, _TCHAR* argv[])
- {
- __try
- {
- MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);
- // 除零,人为的使程序崩溃
- //
- int i = 13;
- int j = 0;
- int m = i / j;
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- // 在这里添加处理程序崩溃情况的代码
- //
- // 这里以弹出一个对话框为例子
- //
- MessageBox(NULL, _T("Message from '__except' section"), _T("Test"), MB_OK);
- }
- MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);
- return 0;
- }
编译上面的代码。运行生成的EXE,会依次弹出下面的对话框。
可以看出,在异常处理代码被调用执行后(except块中的代码),程序继续可以继续运行,并正常退出,并没有崩溃!通过使用__try/__except可以捕捉到任何类型的异常,并保证程序不会崩溃!(想想这是多么的神奇,一个程序永远不会崩溃!)
下面解释一下except中表达式各个值的含义:
EXCEPTION_CONTINUE_SEARCH 异常没有被处理,继续向上抛出。如果更上层的代码没有异常捕捉机制,程序就会崩溃。
EXCEPTION_CONTINUE_EXECUTION 异常已经被处理,返回异常发生的地方继续执行。
EXCEPTION_EXECUTE_HANDLER 异常已经被处理,程序继续往后执行。
通过上面的例子可以知道,SEH的异常处理跟C++的异常处理不同,C++的try/catch不能控制异常进程,对于异常,要么处理,要么继续向上抛出。而SEH却能完全控制异常进程,处理完异常之后,还能决定进该进程如何执行。只要SEH运用得当,编写一个永不崩溃的应用程序成为可能。但是SEH有一个致命的弱点,那就是它是一种结构化的异常处理,所以不支持面向对象。下面用具体的VC++控制台程序来说明。
- // 一个有函数调用的类
- //
- class CrashTest
- {
- public:
- CrashTest() {}
- ~CrashTest() {}
- void Test()
- {
- Crash();
- }
- private:
- void Crash()
- {
- // 除零,人为的使程序崩溃
- //
- int i = 13;
- int j = 0;
- int m = i / j;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- __try
- {
- CrashTest test;
- test.Test();
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- // 在这里添加处理程序崩溃情况的代码
- //
- }
- return 0;
- }
上面的代码不能通过编译,VC++编译器会给出这样的错误信息:error C2712: Cannot use __try in functions that require object unwinding。错误原因很简单,try块内使用了对象。
要想解决这个问题,可以把使用对象的逻辑放到一个函数里,然后在try里调用这个函数,来骗过编译器。把上面的代码修改成下面这样就可以通过编译。
- void Test()
- {
- CrashTest test;
- test.Test();
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- __try
- {
- Test();
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- // 在这里添加处理程序崩溃情况的代码
- //
- }
- return 0;
- }
[转]让程序在崩溃时体面的退出之SEH的更多相关文章
- [转]让程序在崩溃时体面的退出之SEH+Dump文件
原文地址:http://blog.csdn.net/starlee/article/details/6649605 在我上篇文章<让程序在崩溃时体面的退出之SEH>中讲解了SEH中try/ ...
- [转]让程序在崩溃时体面的退出之Dump文件
原文地址:http://blog.csdn.net/starlee/article/details/6630816 在我的那篇<让程序在崩溃时体面的退出之CallStack>中提供了一个在 ...
- [转]让程序在崩溃时体面的退出之CallStack
原文地址:http://blog.csdn.net/starlee/article/details/6618849 在我的那篇<让程序在崩溃时体面的退出之Unhandled Exception& ...
- 让程序在崩溃时体面的退出之Dump文件
在我的那篇<让程序在崩溃时体面的退出之CallStack>中提供了一个在程序崩溃时得到CallStack的方法.但是要想得到CallStack,必须有pdb文件的支持.但 ...
- [转]让程序在崩溃时体面的退出之Unhandled Exception
原文地址:http://blog.csdn.net/starlee/article/details/6613424 程序是由代码编译出来的,而代码是由人写的.人非圣贤,孰能无过.所以由人写的代码有缺陷 ...
- 编写的windows程序,崩溃时产生crash dump文件的办法
一.引言 dump文件是C++程序发生异常时,保存当时程序运行状态的文件,是调试异常程序重要的方法,所以程序崩溃时,除了日志文件,dump文件便成了我们查找错误的最后一根救命的稻草.windows程序 ...
- android在程序崩溃时Catch异常并处理
Android系统的"程序异常退出",给应用的用户体验造成不良影响.为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理.通过Th ...
- 让linux中的程序崩溃时生成core文件
当我们的linux程序崩溃的时候,常常会有这样的提示: Segmentation fault (core dumped) 段错误 (核心已转储) 提示说生成了core文件,但是此功能 ...
- 使用SetUnhandledExceptionFilter转储程序崩溃时内存DMP .
关于程序崩溃时转储内存DMP,可以设置注册表,使程序崩溃时自动转储内存DMP,见程序崩溃时利用注册表自动转储内存DMP.本文要介绍的是使用SetUnhandledExceptionFilter函数在程 ...
随机推荐
- arcgis engine - 添加图例,指北针.
esri帮助提供了使用比例尺的方法: Working with map surrounds 主要代码为: public void AddMapSurround(IPageLayout pageLayo ...
- delphi 功能函数大全-备份用
function CheckTask(ExeFileName: string): Boolean;constPROCESS_TERMINATE=$0001;varContinueLoop: BOOL; ...
- 给右键 添加dos命令
reg add "HKEY_CURRENT_USER\Console" /v "ScreenBufferSize" /t REG_DWORD /d 655361 ...
- 三步走起 提升 iOS 审核通过率 下篇
根据2015年的数据统计情况,并结合<苹果应用商店审核指南>,互娱 iOS 预审组通过细分将预审工作划为3大模块:客户端资源检查.应用内容检查和提审资源检查. 在上一篇文章中,Bugly ...
- IOS 在IOS6中设置navigationBar背景图片 会有一条 黑色阴影 --- 解决方案
//给navigationBar设置背景图片 if ([self.navigationController.navigationBar respondsToSelector:@selector(set ...
- Github上图文演示仓库创建
1.注册账号 https://github.com/ 2.注册完账号 创建仓库 a.点击按钮 Start a project b.填写信息,点击按钮 Create repository c.仓库信息( ...
- C语言数据输入与输出
1 概论 C语言提供了跨平台的数据输入输出函数scanf()和printf()函数,它们可以按照指定的格式来解析常见的数据类型,例如整数,浮点数,字符和字符串等等.数据输入的来源可以是文件,控制台以及 ...
- Struts2文件配置 登陆页面
Struts 版本号 struts-2.3.16.3 web.xml 配置 <?xml version=”1.0″ encoding=”UTF-8″?> <web-app versi ...
- MySQL配置文件路径及‘The total number of locks exceeds the lock table size’问题
在删除mysql中的数据时,遇到报错: ERROR 1206 (HY000): The total number of locks exceeds the lock table size 查了查,发现 ...
- Android PackageManager packages.xml文件格式
packages.xml文件存放在/data/system目录下 该文件记录了系统中所有应用程序的包管理相关信息 PmS根据该文件进行包管理的各种操作 标签名称 所包含的值举例 last- ...