[译]C++异常的幕后6:gcc_except_table与personality函数

栏目: 服务器 · 编程工具 · 发布时间: 5年前

内容简介:上次我们了解到,就像throw语句被翻译为一对__cxa_allocate_exception/throw调用,catch块被翻译为一对__cxa_begin/end_catch调用,加上称为CFI(调用帧信息)的对象,来查找着陆垫——函数处理异常之处。我们尚不知道的是_Unwind_如何知道着陆垫在哪里。在一个异常被抛出时,栈上有一组函数;所有CFI内容将让Unwind知道这些是什么函数,但知道每个函数提供哪些着陆垫也是必须的,因此我们可以调用每个函数,核查它是否希望处理这个异常(我们忽略带有多个try/

作者: nicolasbrailo  

上次我们了解到,就像throw语句被翻译为一对__cxa_allocate_exception/throw调用,catch块被翻译为一对__cxa_begin/end_catch调用,加上称为CFI(调用帧信息)的对象,来查找着陆垫——函数处理异常之处。

我们尚不知道的是_Unwind_如何知道着陆垫在哪里。在一个异常被抛出时,栈上有一组函数;所有CFI内容将让Unwind知道这些是什么函数,但知道每个函数提供哪些着陆垫也是必须的,因此我们可以调用每个函数,核查它是否希望处理这个异常(我们忽略带有多个try/catch块的函数)。

要知道着陆垫在哪里,要使用称为gcc_except_table的东西。在函数末尾可以找到这(带有一组CFI):

1

2

3

4

5

6

.LFE1:

    .globl  __gxx_personality_v0

    .section    .gcc_except_table,"a",@progbits

    [...]

.LLSDACSE1:

    .long   _ZTI14Fake_Exception

节.gcc_except_table是所有定位着陆垫信息保存的地方,一旦我们设法分析了personality函数后,我们再来更多地了解它;目前,我们只是说LSDA表示语言特定数据区域,它是personality函数检查对一个函数是否存在任何着陆垫的地方(在回滚栈时,它也用于运行析构函数)。

总之:对每个至少找到一个catch的函数,编译器将把这个语句翻译为一对__cxa_begin_catch/ __cxa_end_catch调用,接着personality函数,被__cxa_throw调用,将为栈上每个函数读gcc_except_table,查找称为LSDA的东西。然后Personality函数将在LSDA里检查一个catch是否能处理一个异常,是否有清理代码运行(这就是在需要时触发析构函数的原因)。

这里我们还可以得到一个有趣的结论:如果我们使用nothrow说明符(或者空的throw指示符),编译器可以为这个方法忽略gcc_except_table。Gcc实现异常的方式,不会对性能产生大的影响,但确实将减小代码大小。Catch是什么?如果在指明nothrow时抛出一个异常,不存在LSDA,personality函数不知道怎么做。在personality函数不知道做什么时,它将调用缺省的异常处理句柄,意味着在大多数情形里从一个nothrow方法抛出将最终调用std::terminate。

现在我们了解了personality函数是什么,我们可以实现它吗?下一节我们来看如何做。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大规模Web服务开发技术

大规模Web服务开发技术

伊藤直也、田中慎司 / 李剑 / 电子工业出版社 / 2011-7 / 59.00元

Hatena是日本最大的Web服务提供商之一,它提供的服务包括关键字(类似于维基百科)、博客、相册等。《大规模Web服务开发技术》由伊藤直也、田中慎司所著,内容主要来自Hatena为学生们举行的暑期实习的课程,内容涵盖广泛,介绍了性能优化、分布式、算法、系统架构等各个方面,甚至还介绍了硬件的经济成本,是运维工程师们必不可少的参考书。书中还包括几个算法实习课题,介绍了压缩算法、全文搜索等算法的实现方......一起来看看 《大规模Web服务开发技术》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具