__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实际机制可能有出入 ...
随机推荐
- quartz2.3.0(四)JobDataMap—带状态集合的定时器内置集合
任务类 package org.quartz.examples.example4; import java.util.Date; import org.quartz.DisallowConcurren ...
- quartz2.3.0(三)cron定义调度周期
cron总结 cron详解参见:<quartz CronExpression表达式> CronTrigger配置完整格式为7个: [秒] [分] [小时] [日] [月] ...
- 使用QMetaObject获取类的属性
const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyCount(); ...
- nginx在Windows环境安装
nginx介绍 nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个HTTP服务器进行网站的发布处理,另外 ...
- C# vb .net实现扭曲角特效滤镜图像处理
在.net中,如何简单快捷地实现Photoshop滤镜组中的扭曲角效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一 ...
- 删除链表的倒数第 n 个节点
难度: 中等 leetcode地址: https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/ 分析: 1 ...
- ubuntu安裝postman遇到問題
@ubuntupc:~/Postman/app$ sudo ./Postman ./Postman: error while loading shared libraries: libgconf-2. ...
- Python——2x和3x的区别汇总
1. 初始解释器编码: 2x:ascii 编码(不自持中文) 3x:unicode编码 推荐全部更换为utf-8 2. 输出方式不同 2x:print ‘你好’2.7版本的两种都支持 3x:print ...
- ubuntu-网络配置文件
vim /etc/NetworkManager/system-connections/Wired connectione 1
- Linux路由:CentOS6的多种玩法
将一台Linux主机作路由器使用,这本是件很容易的事情,利用Linux主机强大的网络功能,很轻松就实现了.这里在虚拟机环境下设定一台CentOS主机通过另一台CentOS主机路由接入Internet网 ...