Chinaunix首页 | 论坛 | 博客
  • 博客访问: 146965
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 401
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-31 22:55
文章分类

全部博文(43)

文章存档

2015年(1)

2014年(25)

2013年(17)

我的朋友

分类: C/C++

2014-02-28 11:29:21

C++ 中的异常和堆栈展开

  1. 在 C++ 异常结构,控件从 throw 语句的移动到可处理该引发类型的第一个 catch 语句。 在 catch 语句时,在引发和捕捉语句之间范围内的任何自动变量在称为 堆栈展开的进程被销毁。 在展开的堆栈,执行如下所示:
  2. 控件由正常顺序执行到达 try 语句。 在 try 中控制的部分执行块。
  3. 如果在控制节执行过程中为引发异常,try 块之后的 catch 子句不会执行。 继续执行在语句中,在后面关联的 try 后的最后一 catch 子句块。
  4. 如果在所控制的执行过程中引发或了控制的部分直接或间接调用的实例,异常对象从由 throw 操作数创建的对象创建的。 (这意味着有可能涉及复制构造函数。)此时,编译器可以在句柄类型,将引发异常或 catch 处理程序中可以处理任何类型的异常的更高的执行上下文查找 catch 子句。 在 try 块之后,catch 处理程序会检查遵循其外观的序列。 如果未找到适当的处理程序,则检查下一个动态封闭的 try 块。 直到最外面的封闭 try 块进行检查前,此过程将继续。
  5. 如果仍未找到匹配的处理程序,或者如果发生异常,在展开过程,但,在处理程序中获取控件之前,预定义的运行时功能 terminate 调用。 如果出现异常,在引发异常后,但,在展开开始之前,terminate 调用。
  6. 如果找到匹配的 catch 处理程序,并且它通过值来捕获,则通过复制异常对象来初始化其形参。 如果通过引用捕获,初始化参数来引用异常对象。 在形参初始化后,展开堆栈的进程开始。 此过程包括完全是构造,但不构在 try 开头之间块与 catch 处理程序和异常的引发站点的任何自动对象的损坏。 析构以构造相反顺序发生。 catch 处理程序中执行和过程继续执行,在最后一个处理程序是后,在不是 catch 处理程序的第一个语句或构造。 控件通过引发的异常仅输入 catch 处理程序,传递 goto 语句或 case 标签。switch 语句。


以下示例演示引发异常时,该堆栈如何展开。 C to the catch statement in main, and unwinds each function along the way." xml:space="preserve" style="margin:0px;padding:0px;border:0px;outline:0px;background-color:transparent;">在线程的执行与在C的 throw 语句中跳转到maincatch 语句,并展开每个功能。 Dummy objects are created and then destroyed as they go out of scope." xml:space="preserve" style="margin:0px;padding:0px;border:0px;outline:0px;background-color:transparent;">请注意Dummy对象被创建并被销毁的顺序,但超出范围。 main, which contains the catch statement." xml:space="preserve" style="margin:0px;padding:0px;border:0px;outline:0px;background-color:transparent;">和函数未完成除main,包含 catch 语句的通知。 A never returns from its call to B(), and B never returns from its call to C()." xml:space="preserve" style="margin:0px;padding:0px;border:0px;outline:0px;background-color:transparent;">功能A从其从不返回对B(),并且,B从其从不返回对C()。 Dummy pointer and the corresponding delete statement, and then run the program, notice that the pointer is never deleted." xml:space="preserve" style="margin:0px;padding:0px;border:0px;outline:0px;background-color:transparent;">如果取消注释Dummy指针的定义和对应 delete 语句,然后运行程序,请注意指针不会删除。 这将显示可能发生的问题,当函数不提供一个异常确保时。 有关更多信息,请参见如何:设计异常。 如果批注 catch 语句,可以观察发生了什么由于未经处理的异常,那么,当程序终止。


#include 
#include 
using namespace std;
 
class MyException{};
class Dummy
{
    public:
    Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); }
    Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); }
    ~Dummy(){ PrintMsg("Destroyed Dummy:"); }
    void PrintMsg(string s) { cout << s  << MyName <<  endl; }
    string MyName; 
    int level;
};
 
 
void C(Dummy d, int i)
{ 
    cout << "Entering FunctionC" << endl;
    d.MyName = " C";
    throw MyException();   
 
    cout << "Exiting FunctionC" << endl;
}
 
void B(Dummy d, int i)
{
    cout << "Entering FunctionB" << endl;
    d.MyName = "B";
    C(d, i + 1);   
    cout << "Exiting FunctionB" << endl; 
}
 
void A(Dummy d, int i)
{ 
    cout << "Entering FunctionA" << endl;
    d.MyName = " A" ;
  //  Dummy* pd = new Dummy("new Dummy"); //Not exception safe!!!
    B(d, i + 1);
 //   delete pd; 
    cout << "Exiting FunctionA" << endl;   
}
 
 
int main()
{
    cout << "Entering main" << endl;
    try
    {
        Dummy d(" M");
        A(d,1);
    }
    catch (MyException& e)
    {
        cout << "Caught an exception of type: " << typeid(e).name() << endl;
    }
 
    cout << "Exiting main." << endl;
    char c;
    cin >> c;
}
 
/* Output:
    Entering main
    Created Dummy: M
    Copy created Dummy: M
    Entering FunctionA
    Copy created Dummy: A
    Entering FunctionB
    Copy created Dummy: B
    Entering FunctionC
    Destroyed Dummy: C
    Destroyed Dummy: B
    Destroyed Dummy: A
    Destroyed Dummy: M
    Caught an exception of type: class MyException
    Exiting main.
 
*/


阅读(2457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~