Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
361 views
in Technique[技术] by (71.8m points)

g++ - What is the VTable Layout and VTable Pointer Location in C++ Objects in GCC 3.x and 4.x?

I am looking for details of the VTable structure, order and contents, and the location of the vtable pointers within objects.

Ideally, this will cover single inheritance, multiple inheritance, and virtual inheritance.

References to external documentation would also be appreciated

Documentation of GCC 4.0x class layout is here and the Itanium, and more broadly GNU, ABI layout documents are here.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A virtual table is generally treated as an array of function pointers, although compilers are free to put data pointers (in MI and VI scenarios, or to typeinfos), integers (for fixups), or sentinel elements (such as NULL pointers) into it as well. The layout is generally compiler-specific (or ABI-specific where multiple C++ compilers share an ABI), but stable provided the classes being compiled have stable interfaces (otherwise you'd have to recompile your code all the time, and that's a drag). There are also additional tables that are needed to handle corner cases involving virtual and multiple inheritance, and to make sure that virtual calls during derived class construction behave as the Standard says they should under those circumstances (those are what the VTTs and construction tables in the output below are for).

As to the specific case of GCC 4.x: the -fdump-class-hierarchy switch indeed acts as described (and then some). I tested it on Coliru using the sample code below:

struct Base
{
    virtual ~Base() {}
    virtual void f() = 0;
};

struct OtherBase
{
    virtual ~OtherBase() {}
    virtual void g() {}
};

struct Derived: public Base
{
    virtual ~Derived() {}
    virtual void f() {}
};

struct MultiplyDerived: public Base, public OtherBase
{
    virtual ~MultiplyDerived() {}
    virtual void f() {}
    virtual void g() {}
};

struct OtherDerived: public Base
{
    virtual ~OtherDerived() {}
    virtual void f() {}
};

struct DiamondDerived: public Derived, public OtherDerived
{
    virtual ~DiamondDerived() {}
    virtual void f() {}
};

struct VirtuallyDerived: virtual public Base
{
    virtual ~VirtuallyDerived() {}
    virtual void f() {}
};

struct OtherVirtuallyDerived: virtual public Base
{
    virtual ~OtherVirtuallyDerived() {}
    virtual void f() {}
};

struct VirtuallyDiamondDerived: public VirtuallyDerived, public OtherVirtuallyDerived
{
    virtual ~VirtuallyDiamondDerived() {}
    virtual void f() {}
};

struct DoublyVirtuallyDiamondDerived: virtual public VirtuallyDerived, virtual public OtherVirtuallyDerived
{
    virtual ~DoublyVirtuallyDiamondDerived() {}
    virtual void f() {}
};

struct MixedVirtuallyDerived: virtual public Base, public OtherBase
{
    virtual ~MixedVirtuallyDerived() {}
};

struct MixedVirtuallyDiamondDerived: public VirtuallyDerived, public MixedVirtuallyDerived
{
    virtual ~MixedVirtuallyDiamondDerived() {}
    virtual void f() {}
    virtual void g() {}
};

struct VirtuallyMultiplyDerived: virtual public Base, virtual public OtherBase
{
    virtual ~VirtuallyMultiplyDerived() {}
};

struct OtherVirtuallyMultiplyDerived: virtual public Base, virtual public OtherBase
{
    virtual ~OtherVirtuallyMultiplyDerived() {}
};

struct MultiplyVirtuallyDiamondDerived: public VirtuallyMultiplyDerived, public OtherVirtuallyMultiplyDerived
{
    virtual ~MultiplyVirtuallyDiamondDerived() {}
    virtual void f() {}
    virtual void g() {}
};

and received from G++ (mangled name guide: TI's are typeinfos, TV's are vtables, and Th's and Tv's are thunks used to make correct virtual calls in the presence of multiple and/or virtual inheritance):

Vtable for Base

Base::_ZTV4Base: 5u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI4Base)

16    0u

24    0u

32    (int (*)(...))__cxa_pure_virtual


Class Base

   size=8 align=8

   base size=8 base align=8

Base (0x0x7fd42c0355a0) 0 nearly-empty

    vptr=((& Base::_ZTV4Base) + 16u)


Vtable for OtherBase

OtherBase::_ZTV9OtherBase: 5u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI9OtherBase)

16    (int (*)(...))OtherBase::~OtherBase

24    (int (*)(...))OtherBase::~OtherBase

32    (int (*)(...))OtherBase::g


Class OtherBase

   size=8 align=8

   base size=8 base align=8

OtherBase (0x0x7fd42c035600) 0 nearly-empty

    vptr=((& OtherBase::_ZTV9OtherBase) + 16u)


Vtable for Derived

Derived::_ZTV7Derived: 5u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI7Derived)

16    (int (*)(...))Derived::~Derived

24    (int (*)(...))Derived::~Derived

32    (int (*)(...))Derived::f


Class Derived

   size=8 align=8

   base size=8 base align=8

Derived (0x0x7fd42c02d138) 0 nearly-empty

    vptr=((& Derived::_ZTV7Derived) + 16u)

  Base (0x0x7fd42c035660) 0 nearly-empty

      primary-for Derived (0x0x7fd42c02d138)


Vtable for MultiplyDerived

MultiplyDerived::_ZTV15MultiplyDerived: 11u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI15MultiplyDerived)

16    (int (*)(...))MultiplyDerived::~MultiplyDerived

24    (int (*)(...))MultiplyDerived::~MultiplyDerived

32    (int (*)(...))MultiplyDerived::f

40    (int (*)(...))MultiplyDerived::g

48    (int (*)(...))-8

56    (int (*)(...))(& _ZTI15MultiplyDerived)

64    (int (*)(...))MultiplyDerived::_ZThn8_N15MultiplyDerivedD1Ev

72    (int (*)(...))MultiplyDerived::_ZThn8_N15MultiplyDerivedD0Ev

80    (int (*)(...))MultiplyDerived::_ZThn8_N15MultiplyDerived1gEv


Class MultiplyDerived

   size=16 align=8

   base size=16 base align=8

MultiplyDerived (0x0x7fd42c04aaf0) 0

    vptr=((& MultiplyDerived::_ZTV15MultiplyDerived) + 16u)

  Base (0x0x7fd42c0356c0) 0 nearly-empty

      primary-for MultiplyDerived (0x0x7fd42c04aaf0)

  OtherBase (0x0x7fd42c035720) 8 nearly-empty

      vptr=((& MultiplyDerived::_ZTV15MultiplyDerived) + 64u)


Vtable for OtherDerived

OtherDerived::_ZTV12OtherDerived: 5u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI12OtherDerived)

16    (int (*)(...))OtherDerived::~OtherDerived

24    (int (*)(...))OtherDerived::~OtherDerived

32    (int (*)(...))OtherDerived::f


Class OtherDerived

   size=8 align=8

   base size=8 base align=8

OtherDerived (0x0x7fd42c02d1a0) 0 nearly-empty

    vptr=((& OtherDerived::_ZTV12OtherDerived) + 16u)

  Base (0x0x7fd42c035780) 0 nearly-empty

      primary-for OtherDerived (0x0x7fd42c02d1a0)


Vtable for DiamondDerived

DiamondDerived::_ZTV14DiamondDerived: 10u entries

0     (int (*)(...))0

8     (int (*)(...))(& _ZTI14DiamondDerived)

16    (int (*)(...))DiamondDerived::~DiamondDerived

24    (int (*)(...))DiamondDerived::~DiamondDerived

32    (int (*)(...))DiamondDerived::f

40    (int (*)(...))-8

48    (int (*)(...))(& _ZTI14DiamondDerived)

56    (int (*)(...))DiamondDerived::_ZThn8_N14DiamondDerivedD1Ev

64    (int (*)(...))DiamondDerived::_ZThn8_N14DiamondDerivedD0Ev

72    (int (*)(...))DiamondDerived::_ZThn8_N14DiamondDerived1fEv


Class DiamondDerived

   size=16 align=8

   base size=16 base align=8

DiamondDerived (0x0x7fd42c0625b0) 0

    vptr=((& DiamondDerived::_ZTV14DiamondDerived) + 16u)

  Derived (0x0x7fd42c02d208) 0 nearly-empty

      primary-for DiamondDerived (0x0x7fd42c0625b0)

    Base (0x0x7fd42c0357e0) 0 nearly-empty

        primary-for Derived (0x0x7fd42c02d208)

  OtherDerived (0x0x7fd42c02d270) 8 nearly-empty

      vptr=((& DiamondDerived::_ZTV14DiamondDerived) + 56u)

    Base (0x0x7fd42c035840) 8 nearly-empty

        primary-for OtherDerived (0x0x7fd42c02d270)


Vtable for VirtuallyDerived

VirtuallyDerived::_ZTV16VirtuallyDerived: 8u entries

0     0u

8     0u

16    0u

24    (int (*)(...))0

32    (int (*)(...))(& _ZTI16VirtuallyDerived)

40    (int (*)(...))VirtuallyDerived::~VirtuallyDerived

48    (int (*)(...))VirtuallyDerived::~VirtuallyDerived

56    (int (*)(...))VirtuallyDerived::f


VTT for VirtuallyDerived

VirtuallyDerived::_ZTT16VirtuallyDerived: 2u entries

0     ((& VirtuallyDerived::_ZTV16VirtuallyDerived) + 40u)

8     ((& VirtuallyDerived::_ZTV16VirtuallyDerived) + 40u)


Class VirtuallyDerived

   size=8 align=8

   base size=8 base align=8

VirtuallyDerived (0x0x7fd42c02d2d8) 0 nearly-empty

    vptridx=0u vptr=((& VirtuallyDerived::_ZTV16VirtuallyDerived) + 40u)

  Base (0x0x7fd42c0358a0) 0 nearly-empty virtual

      primary-for VirtuallyDerived (0x0x7fd42c02d2d8)

      vptridx=8u vbaseoffset=-40


Vtable for OtherVirtuallyDerived

OtherVirtuallyDerived::_ZTV21OtherVirtuallyDerived: 8u entries

0     0u

8     0u

16    0u

24    (int (*)(...))0

32    (int (*)(...))(& _ZTI21OtherVirtuallyDerived)

40    (int (*)(...))OtherVirtuallyDerived::~OtherVirtuallyDerived

48    (int (*)(...))OtherVirtuallyDerived::~OtherVirtuallyDerived

56    (int (*)(...))OtherVirtuallyDerived::f


VTT for OtherVirtuallyDerived

OtherVirtuallyDerived::_ZTT21OtherVirtuallyDerived: 2u entries

0     ((& OtherVirtuallyDerived::_ZTV21OtherVirtuallyDerived) + 40u)

8     ((& OtherVirtuallyDerived::_ZTV21OtherVirtuallyDerived) + 40u)


Class OtherVirtuallyDerived

   size=8 align=8

   base size=8 base align=8

OtherVirtuallyDerived (0x0x7fd42c02d340) 0 nearly-empty

    vptridx=0u vptr=((& OtherVirtuallyDerived::_ZTV21OtherVirtuallyDerived) + 40u)

  Base (0x0x7fd42c035900) 0 nearly-empty virtual

      primary-for OtherVirtuallyDerived (0x0x7fd42c02d340)

      vptridx=8u vbaseoffset=-40


Vtable for VirtuallyDiamondDerived

VirtuallyDiamondDerived::_ZTV23VirtuallyDiamondDerived: 16u entries

0     0u

8     0u

16    0u

24    (int (*)(...))0

32    (int (*)(...))(& _ZTI23VirtuallyDiamondDerived)

40    (int (*)(...))VirtuallyDiamondDerived::~VirtuallyDiamondDerived

48    (int (*)(...))VirtuallyDiamondDerived::~VirtuallyDiamondDerived

56    (int (*)(...))VirtuallyDiamondDerived::f

64    18446744073709551608u

72    18446744073709551608u

80    18446744073709551608u

88    (int (*)(...))-8

96    (int (*)(...))(& _ZTI23VirtuallyDiamondDerived)

104   (int (*)(...))VirtuallyDiamondDerived::_ZThn8_N23VirtuallyDiamondDerivedD1Ev

112   (int (*)(...))VirtuallyDiamondDerived::_ZThn8_N23VirtuallyDiamondDerivedD0Ev

120   (int (*)(...))VirtuallyDiamondDerived::_ZThn8_N23VirtuallyDiamondDerived1fEv


Construction vtable for VirtuallyDerived (0x0x7fd42c02d3a8 instance) in VirtuallyDiamondDerived

VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived0_16VirtuallyDerived: 8u entries

0     0u

8     0u

16    0u

24    (int (*)(...))0

32    (int (*)(...))(& _ZTI16VirtuallyDerived)

40    0u

48    0u

56    (int (*)(...))VirtuallyDerived::f


Construction vtable for OtherVirtuallyDerived (0x0x7fd42c02d410 instance) in VirtuallyDiamondDerived

VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived8_21OtherVirtuallyDerived: 15u entries

0     18446744073709551608u

8     0u

16    0u

24    (int (*)(...))0

32    (int (*)(...))(& _ZTI21OtherVirtuallyDerived)

40    0u

48    0u

56    (int (*)(...))OtherVirtuallyDerived::f

64    8u

72    8u

80    (int (*)(...))8

88    (int (*)(...))(& _ZTI21OtherVirtuallyDerived)

96    0u

104   0u

112   (int (*)(...))OtherVirtuallyDerived::_ZTv0_n32_N21OtherVirtuallyDerived1fEv


VTT for VirtuallyDiamondDerived

VirtuallyDiamondDerived::_ZTT23VirtuallyDiamondDerived: 7u entries

0     ((& VirtuallyDiamondDerived::_ZTV23VirtuallyDiamondDerived) + 40u)

8     ((& VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived0_16VirtuallyDerived) + 40u)

16    ((& VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived0_16VirtuallyDerived) + 40u)

24    ((& VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived8_21OtherVirtuallyDerived) + 40u)

32    ((& VirtuallyDiamondDerived::_ZTC23VirtuallyDiamondDerived8_21OtherVirtuallyDerived) + 96u)

40    ((& VirtuallyDiamondDerived::_ZTV23VirtuallyDiamondDerived) + 40u)

48    ((& VirtuallyDiamondDerived::_ZTV23VirtuallyDiamondDerived) + 104u)


Class VirtuallyDiamon

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...