Skip to content

Dump class memory layout

dump class memory layout是后续探索的一个重要工具。

clang

thegreenplace Dumping a C++ object's memory layout with Clang

g++

stackoverflow Print layout of C++ object with g++ compiler

Is there a way to print the layout of a C++ object using the g++ compiler or any other means. A simplified example (assuming int takes 4 bytes)

A

Looking at the man pages, -fdump-class-hierarchy maybe?

测试1: 单个polymorphic class

class person
{
public:
        virtual void work(){}
        virtual void eat(){}
        virtual void money(){}
        void sleep(){} //只是声明静态成员,函数存放在代码段,并不占用这个类的空间
private:
        int id=2;
};
int main()
{

}
// g++ test.cpp -fdump-class-hierarchy

输出如下:

Vtable for person
person::_ZTV6person: 5u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI6person)
16    (int (*)(...))person::work
24    (int (*)(...))person::eat
32    (int (*)(...))person::money

Class person
   size=16 align=8
   base size=12 base align=8
person (0x0x7f15f84874e0) 0
    vptr=((& person::_ZTV6person) + 16u)

一、ZTVZTI 是什么含义?

在 shaharmike C++ vtables - Part 1 - Basics 中,对此进行了回答

Note: we’re looking at demangled symbols. If you really want to know, _ZTV is a prefix for vtable, _ZTS is a prefix for type-string (name) and _ZTI is for type-info.

可以看到:

1、ZTVV 的含义是 **v**table

2、ZTII 的含义是 type-**i**nfo

3、ZTSS 的含义是 type-**s**tring

二、vptr=((& person::_ZTV6person) + 16u)中,为什么要+ 16u

这要结合如下内容来看:

Vtable for person
person::_ZTV6person: 5u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI6person)
16    (int (*)(...))person::work
24    (int (*)(...))person::eat
32    (int (*)(...))person::money

可以看到 person::_ZTV6person 的前两个entry不是virtual function的,所以需要 +16 以pass这两个entry。

关于这一点,在 shaharmike C++ vtables - Part 1 - Basics 中,也进行了分析


关于上述输出的解释可以参见:

1、shaharmike C++ vtables - Part 1 - Basics

测试2: polymorphic class inheritance

class person
{
public:
    virtual void work()
    {
    }
    virtual void eat()
    {
    }
    virtual void money()
    {
    }
    void sleep()
    {
    } //只是声明静态成员,函数存放在代码段,并不占用这个类的空间
private:
    int id = 2;
};

class teacher: public person
{
public:
    virtual void work() override
    {
    }
};
int main()
{

}
// g++ test.cpp -fdump-class-hierarchy

输出如下:

Vtable for person
person::_ZTV6person: 5u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI6person)
16    (int (*)(...))person::work
24    (int (*)(...))person::eat
32    (int (*)(...))person::money

Class person
   size=16 align=8
   base size=12 base align=8
person (0x0x7f4e75a604e0) 0
    vptr=((& person::_ZTV6person) + 16u)

Vtable for teacher
teacher::_ZTV7teacher: 5u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI7teacher)
16    (int (*)(...))teacher::work
24    (int (*)(...))person::eat
32    (int (*)(...))person::money

Class teacher
   size=16 align=8
   base size=12 base align=8
teacher (0x0x7f4e75a55138) 0
    vptr=((& teacher::_ZTV7teacher) + 16u)
  person (0x0x7f4e75a60540) 0
      primary-for teacher (0x0x7f4e75a55138)

MSCV

参见:

1、csdn C++ 虚函数和虚函数表详解(底层分析、代码测试)

gdb

参见:

1、 C++ vtables - Part 1 - Basics