__try __except与__try __finally的嵌套使用以及__finally的调用时机
原文:https://blog.csdn.net/SwordArcher/article/details/82465522
try-finally语句的语法与try-except很类似,稍有不同的是,__finally后面没有一个表达式,这是因为try- finally语句的作用不是用于异常处理,所以它不需要一个表达式来判断当前异常错误的种类。另外,与try-except语句类似,try- finally也可以是多层嵌套的,并且一个函数内可以有多个try-finally语句,不管它是嵌套的,或是平行的。当然,try-finally多层嵌套也可以是跨函数的。一个__try可以对应一个__except或者一个__finally,但是不能有__try __except __finally这样的结构,而__try __except和__try __finally俩者可以相互嵌套使用,__finally中的代码,无论是否遇到异常,都会被调用,但它的调用时机会因实际情况而异。
一、__try __finally结构正常运行,顺序执行到__finally(没有异常情况):
void main()
{
puts("hello");
__try
{
puts("__try块中");
}
__finally
{
puts("__finally块中");
}
puts("world");
}
打印情况如下: 顺序执行,world在__finally之后正常打印
hello
__try块中
__finally块中
world
二、goto语句或return语句引发的程序控制流离开当前__try块作用域时,系统自动完成对__finally块代码的调用
void main()
{
__try
{
puts("__try块中");
return; //return语句直接让函数返回
}
__finally
{
puts("__finally块中");
}
puts("此处不会执行");
}
打印结果为: __try块中
__finally块中
三、在某个__try块中出现异常时,导致程序控制流离开当前__try块作用域,去寻找对应的__except块,
如果对应的__except块不能处理这个异常则继续向上寻找可以处理这个异常的__except块,
当找到可以处理异常的__except的时候(异常被识别),在进入这个__except块作用域之前,调用之前的__finally的代码,
然后在执行__except中的代码,如下:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std; void test()
{
int * p = 0x00000000; // pointer to NULL
__try
{
puts(" in try2 ");
__try
{
puts(" in try3 ");
* p = ; //导致一个存储异常
puts(" 这里不会被执行到 ");
}
__finally
{
puts(" in finally ");
}
puts(" 这里也不会被执行到 ");
}
__except (puts(" in filter 1 "), EXCEPTION_CONTINUE_SEARCH) //不在当前except块处理,继续寻找可以处理此异常的except块
{
puts(" in except 1 "); //此块不会被执行,所以不会打印
}
} void main()
{
puts(" hello "); __try
{
puts(" in try1 ");
__try
{
test();
}
__except (puts(" in filter 2 "), EXCEPTION_CONTINUE_SEARCH) //不在当前except块处理,继续寻找可以处理此异常的except块
{
puts(" in except 2 "); //此块不会被执行,所以不会打印
}
}
__except (puts(" in filter 3"), EXCEPTION_EXECUTE_HANDLER) //异常被识别,可以在此except块中对异常进行处理
{
puts(" in except 3 ");
puts(" world ");
}
}
打印结果如下图: hello
in try1
in try2
in try3
in filter
in filter
in filter
in finally
in except
world
无论是第 2种,还是第3种情况,毫无疑问,它们都会引起很大的系统开销,编译器在编译此类程序代码时,它会为这两种情况准备很多的额外代码。一般第2种情况,被称为“局部展开(LocalUnwinding)”;第3种情况,被称为“全局展开(GlobalUnwinding), 第3种情况,也即由于出现异常而导致的“全局展开”,对于程序员而言,这也许是无法避免的,因为你在利用异常处理机制提高程序可靠健壮性的同时,不可避免的会引起性能上其它的一些开销但是,对于第2种情况,程序员完全可以有效地避免它,避免“局部展开”引起的不必要的额外开销。实际这也是与结构化程序设计思想相一致的,也即一个程序模块应该只有一个入口和一个出口,程序模块内尽量避免使用goto语句等。但是,话虽如此,有时为了提高程序的可读性,程序员在编写代码时,有时可能不得不采用一些与结构化程序设计思想相悖的做法,例如,在一个函数中,可能有多处的return语句。针对这种情况,SEH提供了一种非常有效的折衷方案,那就是__leave关键字所起的作用,它既具有像goto语句和return语句那样类似的作用(由于检测到某个程序运行中的错误,需要马上离开当前的 __try块作用域),但是又避免了“局部展开” 的额外开销。
---------------------
void test()
{
puts("hello");
__try
{
int* p;
puts("__try块中");
__leave; //直接跳出当前的__try作用域
p = ;
*p = ;
}
__finally
{
puts("__finally块中");
}
puts("world");
} void main()
{
__try
{
test();
}
__except ()
{
puts("__except块中");
}
}
打印如下: hello
__try块中
__finally块中
world
__try __except与__try __finally的嵌套使用以及__finally的调用时机的更多相关文章
- VC++ 异常处理 __try __except的用法
转载:https://blog.csdn.net/jiaxiaokai/article/details/50983867 __try __except的用法: __try __except是windo ...
- 异常处理__try{}__except(EXCEPTION_EXECUTE_HANDLER){}
在一个函数中不能混合使用 try{}catch(CException *e){} 与 __try{}__except(EXCEPTION_EXECUTE_HANDLER){} 编译时报错 error ...
- 窥探try ... catch与__try ... __except的区别
VC中的这两个东西肯定谁都用过, 不过它们之间有什么区别, 正好有时间研究了一下, 如果有错误欢迎拍砖.基于VC2005, 32位XP 平台测试通过. 估计对于其他版本的VC和操作系统是不通用的. 1 ...
- 转:Repeater嵌套绑定Repeater以及内层调用外层数据
<table border=" style="margin-bottom: 5px" width="100%"> <asp:Repe ...
- Repeater嵌套绑定Repeater以及内层调用外层数据
aspx: <table border=" style="margin-bottom: 5px" width="100%"> <as ...
- SEH分析笔记(X64篇)
SEH分析笔记(X64篇) v1.0.0 boxcounter 历史: v1.0.0, 2011-11-4:最初版本. [不介意转载,但请注明出处 www.boxcounter.com 附件里有本文 ...
- SEH-关于捕获memcpy的异常
网上有说memcpy是C语言写的,没有异常处理机制. 但是貌似SEH可以处理. SEH("Structured Exception Handling"),即结构化异常处理·是(wi ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 【转】《windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
随机推荐
- idea 中激活 JRebel
JRebel介绍: JRebel是一款JVM插件,它使得Java代码修改后不用重启系统,立即生效.IDEA上原生是不支持热部署的,一般更新了 Java 文件后要手动重启 Tomcat 服务器,修改才能 ...
- 未能加载文件或程序集system.web.extensions解决方法
发现未能加载文件或程序集的错误,这是由于我的机器上没有安装Ajax的原因.问题解决后,整理如下:表现:1."System.Web.Extensions, Version=1.0.61025.0, Cu ...
- python day 8: re模块补充,导入模块,hashlib模块,字符串格式化,模块知识拾遗,requests模块初识
目录 python day 8 1. re模块补充 2. import模块导入 3. os模块 4. hashlib模块 5. 字符串格式:百分号法与format方法 6. 模块知识拾遗 7. req ...
- 转换属性transform
transform: rotate(45deg);旋转 rotate(值) 值为正,表示元素顺时针旋转 值为负,表示元素逆时针旋转 transform: translate(200px,100px); ...
- UI5-技术篇-JS函数eval动态执行
<html lang="en"> <head> <meta charset="utf-8" /> <title> ...
- Jwt Token 令牌
/* 采用JWT的生成TOKEN,及APP登录Token的生成和解析 */ public class JwtTokenUtil { /** * token秘钥 */ public static fin ...
- DRF 视图初识
from django.shortcuts import render from rest_framework.generics import ListAPIView,CreateAPIView,Up ...
- MySQL Binlog--PURGE MASTER LOGS失败
问题背景: 在我们磁盘空间维护策略中,BINLOG的默认保留期限为7天,但当磁盘空间不足时,会根据磁盘空间使用率自动清理超过一定数量的BINLOG. 问题原因: 某服务器上报磁盘空间不足,登录服务器发 ...
- sqlserver数据库的启动
sqlserver实例几种启动的方法: (1)在WINDOWS服务控制台里手动启动,或者自动启动(默认) 第二种方式是SQLSERVER本身自已提供的启动方式,可以手动启动 (3)在SQLSERVER ...
- windows+phpstudy(apache) 以cgi方式运行python
Apache配置 在httpd.conf中查找DocumentRoot: +ExecCGI 支持cgi DocumentRoot "F:\phpStud\PHPTutorial\WWW&qu ...