天天看点

Linux Debugging(四): 使用GDB来理解C++ 对象的内存布局(多重继承,虚继承)2、带有虚函数的单一继承3. 多重继承,包含有相同的父类4. 虚拟继承

      前一段时间再次拜读《inside the c++ object model》 深入探索c++对象模型,有了进一步的理解,因此我也写了四篇博文算是读书笔记:

program transformation semantics (程序转换语义学)

the semantics of copy constructors(拷贝构造函数之编译背后的行为)

the semantics of constructors: the default constructor (默认构造函数什么时候会被创建出来)

the semantics of data: data语义学 深入探索c++对象模型

     这些文章都获得了很大的浏览量,虽然类似的博文原来都有,可能不容易被现在仍活跃在csdn blog的各位同仁看到吧。因此萌生了接着将这这本书读完的同时,再接着谈一下我的理解,或者说读书笔记。

     关于c++虚函数,很多博文从各个角度来探究虚函数是如何实现的,或者说编译器是如何实现虚函数的。比较经典的文章有陈皓先生的《c++虚函数表解析》和《c++对象内存布局》。本文通过gdb来从另外一个角度来理解c++

object的内存布局,一来熟悉语言背后编译器为了实现语言特性为我们做了什么;二来熟悉使用gdb来调试程序。

      同时,本文也将对如何更好的理解c++语言提供了一个方法:使用gdb,可以很直观的理解编译器的实现,从根本上掌握c++!我们不单单只会开车,还应该知道车的内部的构造。

编译时不要忘记-g,使得gdb可以把各个地址映射成函数名。

解释一下gdb的命令:

set p obj <on/off>: 在c++中,如果一个对象指针指向其派生类,如果打开这个选项,gdb会自动按照虚方法调用的规则显示输出,如果关闭这个选项的话,gdb就不管虚函数表了。这个选项默认是off。 使用show print object查看对象选项的设置。

set p pertty <on/off>: 按照层次打印结构体。可以从设置前后看到这个区别。on的确更容易阅读。

就是打印虚函数表了。因为知道是两个,可以仅仅打印2个元素。为了知道下一个存储了什么信息,我们打印了3个值。实际上后几个元素存储了parent 和child的typeinfo name和typeinfo。

总结:

对于单一继承,

1. vptr存储到了object的开始。

2. 在vptr之后,从parent开始的data member按照声明顺序依次存储。

Linux Debugging(四): 使用GDB来理解C++ 对象的内存布局(多重继承,虚继承)2、带有虚函数的单一继承3. 多重继承,包含有相同的父类4. 虚拟继承

对应的c++codes:

使用gdb打印的对象内存布局:

可见v3d有两个vptr,指向不同的vtable。首先看一下第一个:

你可以注意到了,vtable打印分行了,可以使用 set p array on将打印的数组分行,以逗号结尾。

注意到该虚函数表以

结尾。在单一继承中是没有这个结束标识的。

接着看第二个vtable:

当然这个只是为了举个例子。现实中很少有人这么干吧。比如访问foo,下面的code将会导致歧义性错误:

 error: request for member boo is ambiguous

multiinheritance.cpp:8: error: candidates are: virtual void point2d::boo()

只能指定具体的subobject才能进行具体调用:

c++ codes:

继承关系图:

Linux Debugging(四): 使用GDB来理解C++ 对象的内存布局(多重继承,虚继承)2、带有虚函数的单一继承3. 多重继承,包含有相同的父类4. 虚拟继承

使用gdb打印object的内存布局:

gdb打印的vptr相关:

有兴趣的话可以看一下反汇编的vtable的构成。

参考:

1. http://stackoverflow.com/questions/6191678/print-c-vtables-using-gdb

2. http://stackoverflow.com/questions/18363899/how-to-display-a-vtable-by-name-using-gdb

尊重原创,转载请注明出处: anzhsoft http://blog.csdn.net/anzhsoft/article/details/18600163

继续阅读