首页 > 代码库 > c++对象内存模型之虚析构函数篇(1)

c++对象内存模型之虚析构函数篇(1)

看了两篇关于c++对象内存模型的文章,来源在这里:

http://blog.csdn.net/haoel/article/details/3081328/

http://blog.csdn.net/haoel/article/details/3081385

文章中讲了多种继承模式中虚函数的实际情况,按我的理解是把单一继承理解好了,其它几种只是一种变种。当然没这文章,我断想不到c++对象内存是这个样子。

文章中讲的情况,唯独没有讲有虚析构函数存在的情形。我学着文章中介绍的方法,用试探的方式找有虚析构函数的对象的内存结构。虚析构函数与一般的虚函数不一样。我也只是初步探讨,希望有人能指点,指指点点也行。

(测试环境为32位window7,ide是devc++)

现在总结如下几种情况:

(1) 单独一个类,有虚析构函数,虚函数

(2) 有继承关系,单一继承,父类无虚析构函数

(3) 有继承关系,单一继承,父类有虚析构函数

(4) 有4吗?暂时不知道,看总结情况

待续,(因为UML正在学着用,又想把文章写的漂亮点,不至于一直看代码,看图会理解得更好。有图有真相是这个意思)

================================================================

 (1) 单独一个类,有虚析构函数,虚函数

    代码如下:

 1 #include <iostream> 2 using namespace std; 3  4 class A 5 { 6        int ia; 7        public: 8        A ():ia(1) 9      {        10       } 11      virtual ~A ()12      {13            cout << "~A" << endl;14      } 15      virtual void f()16      {17           cout << "A:f()" <<endl;18      } 19 };20 21 typedef void (*F)();22 23 int main()24 {25 26      F pf = NULL;27     A *a = new A(); 28     int **p = (int **)a;29     pf = (F)p[0][2];30     pf();31 32     int flag = 2;33     switch(flag)34     {35         case 0:36             pf = (F)p[0][0];37             pf();38             break;39         case 1:40             pf = (F)p[0][1];41             pf();42             break;43         case 2:44             pf = (F)p[0][1];45             pf();46             pf = (F)p[0][0];47             pf();48             break;49     }50     cout << p[1] << endl;    51     cout << p[0][3] << endl;52     cout << sizeof(A) << endl;53 }

 

flag : 0A:f()~A108--------------------分割线---------------------flag : 1A:f()~A491539608--------------------分割线---------------------flag : 2A:f()~A(段错误)

flag为2时,调试得知段错误发生在47行。

下面是对此种情形内存结构的猜测:

类UML(?反正用ArgoUML画的,标准不)描述:

图a.         内存结构猜测-图b:

vptr是虚指针,右边是虚指针函数的内容,即执行的效果。并不是函数体,这只是函数的入口地址,为方便标示才写函数的输出内容,最后那个0是虚指针表的结束标志。

分析:

 内存模型是图b,

全部先执行A f()这个位于虚函数哥末端的虚函数,最后的是结束标志0(这个标志不代表所有的结束标志,有些情况是1,详情见文章开始推荐的文章。有机会整理下1和0的情形)

由flag为0时,执行图b中顶端第一个"~A",ia也能打印出为是1,说明啥,暂时不说(其实也是猜测)

由flag为1时,执行了图b中(自上而下,下次不做说明)第二个"~A",ia打印出来是随机的。这个随机结论可以在多次执行的情况下得到。

由flag为2时,先执行第二个"~A",此时执行顶端的"~A"时出现断错误。与flag为0时ia=1,flag为1时ia结果随机,大胆猜测执行第二个"~A"后,内存已被释放

本人把flag为2时的情形作了调整,先执行p[0][0],再执行p[0][1],没有段错误。输出如下

A:f()~A~A0x5b00c408

结论:

此种情况下内存结构就如图b所示,多个虚函数直接在虚函数表后面排队就行了。并且第二个才是真正的析构函数。至于为什么有两个"~A",原理我不清楚,我猜的也许是错的,我只是看到了现象。目前我的想法是总结所能想到的有虚析构函数的现象。

注:自己分了几个类别进行分析,代码写好,结论也很快就得出来了,但是文章真的很难写好,还要让别人看明白。当然这有助于我自己的思考。下期节目见

 

c++对象内存模型之虚析构函数篇(1)