栈回退(Stack Unwind)机制

“栈回退”是伴随异常处理机制引入 C++ 中的一个新概念,主要用来确保在异常被抛出、捕获并处理后,所有生命期已结束的对象都会被正确地析构,它们所占用的空间会被正确地回收。

受益于栈回退机制的引入,以及 C++ 类所支持的“资源申请即初始化”语意,使得我们终于能够彻底告别既不优雅也不安全的 setjmp/longjmp 调用,简便又安全地实现远程跳转了。我想这也是 C++ 异常处理机制在错误处理以外唯一一种合理的应用方式了。

下面我们就来具体看看编译器是如何实现栈回退机制的:


图3 C++ 栈回退机制

图3中的“FuncUnWind”函数内,所有真实代码均以黑色和蓝色字体标示,编译器生成的代码则由灰色和橙色字体标明。此时,在图2里给出的 nStep 变量和 tblUnwind 成员作用就十分明显了。

nStep 变量用于跟踪函数内局部对象的构造、析构阶段。再配合编译器为每个函数生成的 tblUnwind 表,就可以完成退栈机制。表中的 pfnDestroyer 字段记录了对应阶段应当执行的析构操作(析构函数指针);pObj 字段则记录了与之相对应的对象 this 指针偏移。将 pObj 所指的偏移值加上当前栈框架基址(EBP),就是要代入 pfnDestroyer 所指析构函数的 this 指针,这样即可完成对该对象的析构工作。而 nNextIdx 字段则指向下一个需要析构对象所在的行(下标)。

在发生异常时,异常处理器首先检查当前函数栈框架内的 nStep 值,并通过 piHandler 取得 tblUnwind[] 表。然后将 nStep 作为下标带入表中,执行该行定义的析构操作,然后转向由 nNextIdx 指向的下一行,直到 nNextIdx 为 -1 为止。在当前函数的栈回退工作结束后,异常处理器可沿当前函数栈框架内 piPrev 的值回溯到异常处理链中的上一节点重复上述操作,直到所有回退工作完成为止。

值得一提的是,nStep 的值完全在编译时决定,运行时仅需执行若干次简单的整形立即数赋值(通常是直接赋值给CPU里的某个寄存器)。此外,对于所有内部类型以及使用了默认构造、析构方法(并且它的所有成员和基类也使用了默认方法)的类型,其创建和销毁均不影响 nStep 的值。

注意:如果在栈回退的过程中,由于析构函数的调用而再次引发了异常(异常中的异常),则被认为是一次异常处理机制的严重失败。此时进程将被强行禁止。为防止出现这种情况,应在所有可能抛出异常的析构函数中使用“std::uncaught_exception()”方法判断当前是否正在进行栈回退(即:存在一个未捕获或未完全处理完毕的异常)。如是,则应抑制异常的再次抛出。

http://baiy.cn/doc/cpp/inside_exception.htm#栈回退(Stack_Unwind)机制相关推荐

  1. mysql 白皮书_mysql企业版 《 MySQL企业版中文白皮书 》.cn.doc

    mysql企业版 < MySQL企业版中文白皮书 >.cn mysql企业版 < MySQL企业版中文白皮书 >.cn 导读:就爱阅读网友为您分享以下"< My ...

  2. Nmap手册(转自http://www.nmap.com.cn/doc/manual.shtm)

    译注 该Nmap参考指南中文版由Fei Yang fyang1024@gmail.com和Lei Lililei_721@6611.org 从英文版本翻译而来. 我们希望这将使全世界使用中文的人们更了 ...

  3. 顺丰品牌研究http://www.kiees.cn/sf/express/brand.htm

    顺丰控股股份有限公司,顺丰速运SF,始于1993年,国内速递行业中民族品牌的佼佼者,以其速度快/安全性能高蜚声业界,现已开通海外快递服务,2017年2月完成借壳上市 1993年,顺丰诞生于广东顺德.自 ...

  4. 关于yahoo.com.cn邮箱导入Gmail邮箱验证异常的机制解析及解决办法

    一大早起来,突然就发现雅虎中国的邮箱要关停了,阿里巴巴居然都发了最后通牒了.吐槽一下,国际互联网企业来天朝之后,似乎就没有一个活的很好的,ebay被淘宝赶出了天朝,Google被度娘赶走了,Faceb ...

  5. C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题

    C++ 用异常使得可以将正常执行代码和出错处理区别开来. 比如一个栈,其为空时,调用其一个pop 函数,接下来怎么办? 栈本身并不知道该如何处理,需要通知给其调用者(caller),因为只有调用者清楚 ...

  6. C++异常机制的实现方式和开销分析(作者:白杨)

    C++异常机制的实现方式和开销分析 白杨 http://baiy.cn 在我几年前开始写<C++编码规范与指导>一文时,就已经规划着要加入这样一篇讨论 C++ 异常机制的文章了.没想到时隔 ...

  7. try...catch...效率思考

    今天想要在某程序的插件里面大量使用try...catch来增加程序的健壮性 但是十分担心性能问题,因为该程序是中间件,一旦出现严重的性能问题,将会对整个系统造成负面影响 首先找到的是下面这篇文章: h ...

  8. html显示千分位及小数位,JavaScript 格式化数字、金额、千分位、保留几位小数、舍入舍去…...

    JavaScript 格式化数字.金额.千分位.保留几位小数.舍入舍去- 类库推荐 1. Numeral.js 一个用于格式化和操作数字的JavaScript库.数字可以被格式化为货币,百分比,时间, ...

  9. 保证系统三高:高可用、高性能、高扩展

    高性能包括高并发.低延迟. 高并发: 谷歌搜索:what is high concurrency 垂直扩展.水平扩展方向: https://topic.alibabacloud.com/a/high- ...

  10. 小米4公布会视频地址

    http://www.inpai.com.cn/doc/phone/210255.htm 转载于:https://www.cnblogs.com/lxjshuju/p/6784545.html

最新文章

  1. 我国java发展_Java在我国的应用现状和发展趋势
  2. 扩展Java EE应用程序的基础
  3. HBuilder完成webApp入门(3) 关于webview (转)
  4. 类加载是为了执行静态方法
  5. Facebook田渊栋谈人生挑战与选择
  6. vSAN其实很简单-如何榨干vSAN的最后的空间- Part2(转)
  7. 1.窗体与界面设计-菜单应用实例
  8. 电脑双系统--我想体验不一样的感觉
  9. 脑电EEG代码开源分享 【2.预处理-静息态篇】
  10. DXGI_FORMAT enumeration (dxgiformat.h)
  11. 弱监督论文解读:CADN- 用于表面缺陷检测的基于弱监督学习的分类感知对象检测网络
  12. 如何用matlab做参数估计,参数估计的MATLAB实现
  13. 小技巧 大智慧 实例集
  14. java判断小数位数_java-使用BigDecimal确定小数位数
  15. ​网线水晶头排线图片接线标准
  16. 分享20份小升初超实用简历模板,每套都有自己的风格,可选取适合孩子的
  17. unity 如何实现一个日志上报系统
  18. 智慧校园解决方案:一站式解决校园数字化转型难题
  19. 新华三的背景_新华三的背景_开放融合创新:新华三全力支撑运营商5G赋能百业...
  20. C++ Primer Plus(第6版)读书笔记--c++自定义函数

热门文章

  1. Python关键字keyword
  2. Htmlcssjs 图片轮播,加箭头
  3. 恢复计算机注册表命令,电脑的注册表如果损坏怎么恢复
  4. 「 数学模型 」“三角函数化简公式”小结
  5. 半导体术语-什么CIM
  6. 研发管理工程师笔试题
  7. 极客公园创新大会 IF 2018,用科技主义和独立思维击退喧嚣
  8. log4j 2.x版本 日志按天分割,按文件大小分割
  9. tableau 日周月筛选器_Tableau技巧——快速计算同比和环比(及其衍生)
  10. Python学习---综合练习之Craps赌博游戏