C++对象模型是个常见、且复杂的话题,本文基于Itanium C++ ABI通过程序实践介绍了几种 简单C++继承 场景下对象模型,尤其是存在虚函数的场景,并通过图的方式直观表达内存布局。
本文展示的程序构建情况为Ubuntu,glibc 2.24,gcc 6.3.0。由于clang和gcc编译器都是基于Itanium C++ ABI(详细信息参考gcc ABI policy),因此本文介绍的对象模型对clang编译的程序也基本实用。
虚函数表简介
从类Base_C的界说来看,类占用的空间包括一个虚函数表指针vptr和一个整型变量。由于内存对齐的原因,类占用16字节。
接下来看虚函数表,表中一共有4个entry,每个entry都是函数指针,指向详细的虚函数,因此每个entry在测试的呆板上编译占8字节(指针大小)。
留意看到表中虚析构函数有两个,这现实上是Itanium C++ ABI规定的:
The entries for virtual destructors are <em><strong>actually pairs of entries</strong></em>.
The first destructor, called the <strong>complete object destructor</strong>, performs the destruction without calling delete() on the object.
The second destructor, called the <strong>deleting destructor</strong>, calls delete() after destroying the object.
Both destroy any virtual bases; a separate, non-virtual function, called the base object destructor,
performs destruction of the object but not its virtual base subobjects, and does not call delete().
The <strong>typeinfo</strong> pointer points to the typeinfo object used for RTTI. <em>It is always present</em>.
All entries in each of the virtual tables for a given class must point to the same typeinfo object.
A correct implementation of typeinfo equality is to check pointer equality, except for pointers (directly or indirectly) to incomplete types.
The typeinfo pointer is a valid pointer for polymorphic classes, i.e. those with virtual functions, and is zero for non-polymorphic classes.
复制代码
// offset偏移
The <strong>offset</strong> to top holds the displacement to the top of the object from the location within the object of the virtual table pointer that addresses this virtual table, as a ptrdiff_t. <em>It is always present</em>.
The offset provides a way to find the top of the object from any base subobject with a virtual table pointer. This is necessary for dynamic_cast<void*> in particular.
In a complete object virtual table, and therefore in all of its primary base virtual tables, the value of this offset will be zero.
For the secondary virtual tables of other non-virtual bases, and of many virtual bases, it will be negative. Only in some construction virtual tables will some virtual base virtual tables have positive offsets,
due to a different ordering of the virtual bases in the full object than in the subobject's standalone layout.