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

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

内容简介:上次我们了解到,就像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函数是什么,我们可以实现它吗?下一节我们来看如何做。


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

查看所有标签

猜你喜欢:

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

大转换

大转换

尼古拉斯·卡尔 / 闫鲜宁、张付国 / 中信 / 2016-2 / 49

1、我们这个时代最清醒的思考者之一尼古拉斯·卡尔继《浅薄》《玻璃笼子》之后又一重磅力作。 2、在这部跨越历史、经济和技术领域的著作中,作者从廉价的电力运营方式对社会变革的深刻影响延伸到互联网对我们生活的这个世界的重构性影响。 3、《快公司》《金融时报》《华尔街日报》联袂推荐 简介 早在2003年,尼古拉斯·卡尔先生发表在《哈佛商业评论》上的一篇文章——IT Doesn't ......一起来看看 《大转换》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具