__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实际机制可能有出入 ...
随机推荐
- 【scratch3.0教程】 2.3 奥运五环
(1)编程前的准备 在设计一个作品之前,必须先策划一个脚本,然后再根据脚本,收集或制作素材(图案,声音等),接着就可以启动Scratch,汇入角色.舞台,利用搭程序积木的方式编辑程序,制作出符合脚本的 ...
- quartz2.3.0(七)调度器中断任务执行,手动处理任务中断事件
job任务类 package org.quartz.examples.example7; import java.util.Date; import org.slf4j.Logger; import ...
- IDEA远程DEBUG Tomcat配置
IDEA远程DEBUG Tomcat配置 IDEA远程DEBUG Tomcat很简单,配置如下: 1.修改tomcat服务器配置 打开tomcat/bin/catalina.sh 在空白处添加如下参数 ...
- 网络编程-tcp三次握手和四次挥手
TCP三次握手和四次挥手过程 1.三次握手 (1)三次握手的详述 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向 ...
- JS中的迭代器和生成器
利用迭代器生成一个遍历方法: let arr1 = [1, 2, 3, 11, 22, 13, 24]; function forOf(arr, callback) { // 找到迭代器函数 let ...
- JavaScript_01-script
编译和解释 var a = 0; console.log(a); var b = "abc"; 编译: 一次性把代码转换成 CPU 可以看懂的语言,一行一行执行: 解释:一行一行解 ...
- JavaScript之运算符
(1)赋值运算符 // c+=1; // 相当于c=c+1; // console.log(a++); // 先将a的值赋值给表达式,a再加1 // console.log(++a); // a先加1 ...
- springboot整合tkmybatis
tkmybatis是什么? tkmybatis是为了简化mybatis单表的增删改查而诞生的,极其方便的使用MyBatis单表的增删改查,在使用mybatis单表增删改查时,可以直接调用tkmybat ...
- 挂载nfs提示:mount.nfs: access denied by server while mounting...
出现此类错误原因大致为: 权限问题 防火墙机制问题 共享配置文件问题 搭建好nfs服务后,在client端进行挂载时,提示: [root@web1 media]# mount -t nfs 192.1 ...
- 4.kafka API producer
1.Producer流程首先构建待发送的消息对象ProducerRecord,然后调用KafkaProducer.send方法进行发送.KafkaProducer接收到消息后首先对其进行序列化,然后结 ...