c++ 异常处理(2)(四)

2014-11-24 11:40:51 · 作者: · 浏览: 4
该函数中有catch语句,且能够处理当前的异常,则该catch就是landing pad
2)如果当前函数没有catch或者没有可以处理当前exception的catch语句,则意味着异常还要从当前函数继续往上抛,因而unwind时当前函数有可能要进行相应的清理,此时这些清理局部变量的代码就是landing pad。
从名字上来看,顾名思议,landing pad指的是程序的执行流程在进入当前函数后,最后要转到这里去,很恰当的描述。
当landing pad是catch语句时,这个比较好理解,前面我们一直说清理局部变量的代码,这是什么意思呢?这些清理代码又放在哪里?
为了说明这个问题,我们看一下如下代码:
复制代码
#include
#include
using namespace std;
class cs
{
public:
explicit cs(int i) :i_(i) { cout << "cs constructor:" << i << endl; }
~cs() { cout << "cs destructor:" << i_ << endl; }
private:
int i_;
};
void test_func3()
{
cs c(33);
cs c2(332);
throw 3;
cs c3(333);
cout << "test func3" << endl;
}
void test_func3_2()
{
cs c(32);
cs c2(322);
test_func3();
cs c3(323);
test_func3();
}
void test_func2()
{
cs c(22);
cout << "test func2" << endl;
try
{
test_func3_2();
cs c2(222);
}
catch (int)
{
cout << "catch 2" << endl;
}
}
void test_func1()
{
cout << "test func1" << endl;
try
{
test_func2();
}
catch (...)
{
cout << "catch 1" << endl;
}
}
int main()
{
test_func1();
return 0;
}
复制代码
对于函数test_func3_2()来说,当test_func3()抛出异常后,在unwind的第二阶段,我们知道test_func3_2()中的局部变量c及c2是需要清理的,而c3则不用,那么编译器是怎么生成代码来完成这件事情的呢?当异常发生时,运行时没有办法知道当前哪些变量是需要清理的,因为这个原因编译器在生成代码的时候,在函数的末尾设置了多个出口,使得当异常发生时,可以直接跳到某一段代码就能清理相应的局部变量,我们看看test_func3_2()编译后生成的对应的汇编代码:
复制代码
void test_func3_2()
{
400ca4: 55 push %rbp
400ca5: 48 89 e5 mov %rsp,%rbp
400ca8: 53 push %rbx
400ca9: 48 83 ec 48 sub $0x48,%rsp
cs c(32);
400cad: 48 8d 7d e0 lea 0xffffffffffffffe0(%rbp),%rdi
400cb1: be 20 00 00 00 mov $0x20,%esi
400cb6: e8 9f 02 00 00 callq 400f5a <_ZN2csC1Ei>
cs c2(322);
400cbb: 48 8d 7d d0 lea 0xffffffffffffffd0(%rbp),%rdi
400cbf: be 42 01 00 00 mov $0x142,%esi
400cc4: e8 91 02 00 00 callq 400f5a <_ZN2csC1Ei>
test_func3();
400cc9: e8 5a ff ff ff callq 400c28 <_Z10test_func3v>
cs c3(323);
400cce: 48 8d 7d c0 lea 0xffffffffffffffc0(%rbp),%rdi
400cd2: be 43 01 00 00 mov $0x143,%esi
400cd7: e8 7e 02 00 00 callq 400f5a <_ZN2csC1Ei>
test_func3();
400cdc: e8 47 ff ff ff callq 400c28 <_Z10test_func3v>
400ce1: eb 17 jmp 400cfa <_Z12test_func3_2v+0x56>
400ce3: 48 89 45 b8 mov %rax,0xffffffffffffffb8(%rbp)
400ce7: 48 8b 5d b8 mov 0xffffffffffffffb8(%rbp),%rbx
400ceb: 48 8d 7d c0 lea 0xffffffffffffffc0(%rbp),%rdi #c3的this指针
400cef: e8 2e 02 00 00 callq 400f22 <_ZN2csD1Ev>
400cf4: 48 89 5d b8 mov %rbx,0xffffffffffffffb8(%rbp)
400cf8: eb 0f jmp 400d09 <_Z12test_func3_2v+0x65>
400cfa: 48 8d 7d c0 lea 0xffffffffffffffc0(%rbp),%rdi #c3的this指针
400cfe: e8 1f 02 00 00 callq 400f22 <_ZN2csD1Ev>
400d03: eb 17 jmp 400d1c <_Z12test_func3_2v+0x78>
400d05: 48 89 45 b8 mov %rax,0xffffffffffffffb8(%rbp)
400d09: 48 8b 5d b8 mov 0xffffffffffffffb8(%rbp),%rbx
400d0d: 48 8d 7d d0 lea 0xffffffffffffffd0(%rbp),%rdi #c2的this指针
400d11: e8 0c 02 00 00 callq 400f22 <_ZN2csD1Ev>
400d16: 48 89 5d b8 mov %rbx,0xffffffffffffffb8(%rbp)
400d1a: eb 0f jmp 400d2b <_Z12test_func3_2v+0x87>
400d1c: 48 8d 7d d0 lea 0xffffffffffffffd0(%rbp),%rdi #c2的