原文出处:http://blog.youkuaiyun.com/wuzh1230/article/details/7212817

函数与子函数之间的调用关系可以用一个链来表示,调用连,相关的一个重要数据结构就是栈帧,子函数返回的时候,栈展开,构造在栈上的对象被编译器设置的析构函数析构销毁。


 

类似的,windows上的结构化异常处理也有一个类似的异常处理链,而且这个链刚好也是在栈上构造的,但是和函数正常的链是各自独立的。当某一个子函数发生异常的时候,就不能走正常的调用连返回,进而析构对象;这个时候,需要走异常链来回溯,展开异常调用链,所有附着在异常链上的对象,在异常链的第二次调用(unwind处理,第一次是搜索异常处理者)的时候析构。


 

 函数调用         A ----------------------> B ---------------------> C ------------------------->D


 

正常调用链 CallNode_A--------> CallNode_B ---------->CallNode_C------------>CallNode_D


 

异常链       ExcpNode_A-------> ExcpNode_B------------------------------------------->!!BOMB!!<


 


 

每一个节点都包含了该函数对应的对象的析构操作,正常调用链也好,异常链也好,都是这样的,这些是由C++编译器完成的。每一个call操作,c++编译器产生一个子函数栈帧节点每一个try-catch语句,c++语句构造一个异常链节点


 

但是,如果一个程序员在C函数里面没有写try-catch,但是D函数里面有try-catch语句,而且运行的时候,在D函数里面发生了异常,那么C函数里面的生成的所有对象得不到析构的机会。


 


 

程序代码

 

  1. // debugee.cpp : Defines the entry point for the console application.   
  2. //   
  3.   
  4. #include "stdafx.h"   
  5.   
  6. class Object  
  7. {  
  8. public:  
  9.     Object(const char tag) : m_tag(tag)  
  10.         {printf("Object [%c] %p\n", m_tag, this);};  
  11.   
  12.     ~Object()  
  13.         {printf("~Object [%c] %p\n", m_tag, this);};  
  14.   
  15. private:  
  16.     char m_tag;  
  17. };  
  18.   
  19. void D(void)  
  20. {  
  21.     Object d('D');  
  22.     *(int *)0 = 0;  
  23. }  
  24.   
  25. void C(void)  
  26. {  
  27.     Object c('C');  
  28.     D();  
  29. }  
  30.   
  31.   
  32. void B(void)  
  33. {  
  34.     Object b('B');  
  35.     try  
  36.     {  
  37.         C();  
  38.     }catch(...)  
  39.     {  
  40.         printf("B caught exception.\n");  
  41.     }  
  42. }  
  43.   
  44. void A(void)  
  45. {  
  46.     Object a('A');  
  47.     try  
  48.     {  
  49.         B();  
  50.     }catch(...)  
  51.     {  
  52.         printf("A caught exception.\n");  
  53.     }  
  54. }  
  55.   
  56. int main(int argc, char* argv[])  
  57. {  
  58.     A();  
  59.     return 0;  
  60. }  
// debugee.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

class Object
{
public:
	Object(const char tag) : m_tag(tag)
		{printf("Object [%c] %p\n", m_tag, this);};

	~Object()
		{printf("~Object [%c] %p\n", m_tag, this);};

private:
	char m_tag;
};

void D(void)
{
	Object d('D');
	*(int *)0 = 0;
}

void C(void)
{
	Object c('C');
	D();
}


void B(void)
{
	Object b('B');
	try
	{
		C();
	}catch(...)
	{
		printf("B caught exception.\n");
	}
}

void A(void)
{
	Object a('A');
	try
	{
		B();
	}catch(...)
	{
		printf("A caught exception.\n");
	}
}

int main(int argc, char* argv[])
{
	A();
	return 0;
}



 

 

输出:


 


 

注意:

vc编译器的版本差异和编译选项的差异,vc2005的/EHsc标记。

 

  1. class Object  
  2. {  
  3. public:  
  4.     Object(const char tag) : m_tag(tag)  
  5.     {printf("Object [%c] %p\n", m_tag, this);};  
  6.   
  7.     ~Object()  
  8.     {printf("~Object [%c] %p\n", m_tag, this);};  
  9.   
  10. private:  
  11.     char m_tag;  
  12. };  
  13.   
  14. void E(void)  
  15. {  
  16.     Object e('E');  
  17.     //try   
  18.     {  
  19.         throw("");  
  20.     }  
  21.     //catch (...)   
  22.     {  
  23.   
  24.     }  
  25. }  
  26.   
  27. void D(void)  
  28. {  
  29.     Object d('D');  
  30.     E();  
  31. }  
  32.   
  33. void C(void)  
  34. {  
  35.     Object c('C');  
  36.     D();  
  37. }  
  38.   
  39.   
  40. void B(void)  
  41. {  
  42.     Object b('B');  
  43.     //try   
  44.     {  
  45.         C();  
  46.     }  
  47.     //catch(...)   
  48.     {  
  49.         printf("B caught exception.\n");  
  50.     }  
  51. }  
  52.   
  53. void A(void)  
  54. {  
  55.     Object a('A');  
  56.     try  
  57.     {  
  58.         B();  
  59.     }catch(...)  
  60.     {  
  61.         printf("A caught exception.\n");  
  62.     }  
  63. }  
  64.   
  65. int main(int argc, char* argv[])  
  66. {  
  67.     A();  
  68.     return 0;  
  69. }  
class Object
{
public:
    Object(const char tag) : m_tag(tag)
    {printf("Object [%c] %p\n", m_tag, this);};

    ~Object()
    {printf("~Object [%c] %p\n", m_tag, this);};

private:
    char m_tag;
};

void E(void)
{
    Object e('E');
    //try
    {
        throw("");
    }
    //catch (...)
    {

    }
}

void D(void)
{
    Object d('D');
    E();
}

void C(void)
{
    Object c('C');
    D();
}


void B(void)
{
    Object b('B');
    //try
    {
        C();
    }
    //catch(...)
    {
        printf("B caught exception.\n");
    }
}

void A(void)
{
    Object a('A');
    try
    {
        B();
    }catch(...)
    {
        printf("A caught exception.\n");
    }
}

int main(int argc, char* argv[])
{
    A();
    return 0;
}


不带/EHsc产生的结果符合预期