C++异常的幕后9:捕捉我们第一个异常

原文地址:https://monoinfinito.wordpress.com/2013/04/02/c-exceptions-under-the-hood-9-catching-our-first-exception/

作者:nicolasbrailo 

在上一章我们添加一个_Unwind_可以调用的personality函数,并分析这个personality函数接受的参数。现在是时候向__gxx_personality_v0添加某些真实的行为:在调用__gxx_personality_v0时,我们应该说“是的,这个栈帧确实能够处理这个异常”。

到目前为止,我们已经积累了相当多的经验:我们第一次可以实现一个能够检测何时抛出异常,并宣称“是的,我将处理这个异常”的personality函数。为此,我们必须学习两阶段查找如何工作,因此现在我们可以重新实现我们的personality函数以及我们的抛出测试文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

#include <stdio.h>

#include "throw.h"

 

struct Fake_Exception {};

 

void raise() {

    throw Exception();

}

 

void try_but_dont_catch() {

    try {

        raise();

    } catch(Fake_Exception&) {

        printf("Caught a Fake_Exception!\n");

    }

 

    printf("try_but_dont_catch handled the exception\n");

}

 

void catchit() {

    try {

        try_but_dont_catch();

    } catch(Exception&) {

        printf("Caught an Exception!\n");

    }

 

    printf("catchit handled the exception\n");

}

 

extern "C" {

    void seppuku() {

        catchit();

    }

}

我们的personality函数:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

_Unwind_Reason_Code __gxx_personality_v0 (

                     int version, _Unwind_Action actions, uint64_t exceptionClass,

                     _Unwind_Exception* unwind_exception, _Unwind_Context* context)

{

    if (actions & _UA_SEARCH_PHASE)

    {

        printf("Personality function, lookup phase\n");

        return _URC_HANDLER_FOUND;

    } else if (actions & _UA_CLEANUP_PHASE) {

        printf("Personality function, cleanup\n");

        return _URC_INSTALL_CONTEXT;

    } else {

        printf("Personality function, error\n");

        return _URC_FATAL_PHASE1_ERROR;

    }

}

备注:你可以从我的github repo下载完整的源代码。

让我们运行看发生什么:

1

2

3

4

5

6

alloc ex 1

__cxa_throw called

Personality function, lookup phase

Personality function, cleanup

try_but_dont_catch handled the exception

catchit handled the exception

它能工作,但缺少一些东西:在catch/try块里的catch没有执行!这是因为personality函数告诉Unwind“安装一个上下文”(即重新执行),但它从不说是哪个上下文。在这个情形里,在着陆垫后恢复执行是可能的。下次我们将看到我们如何可以使用.gcc_except_table里的信息(我们的老朋友,LSDA)从指定着陆垫恢复执行。

猜你喜欢

转载自blog.csdn.net/wuhui_gdnt/article/details/89023202