什么&#34; <vtable for =“”a + 16 =“”>&#34;意思?

时间:2015-06-30 03:53:00

标签: c++

这是我的代码。我只是想看一下虚拟继承的内存布局。

#include<iostream>
using namespace std;

class A{
    private:
        int a;
    public:
        virtual void print() const{
            cout << a << endl;
        }

};

class B:public virtual A{
    private:
        int b;
    public:
        void print() const{
            cout << b << endl;
        }
};



int main(){
    A a;
    B b;
    return 0;
}

然后在gdb中,我使用了

p a
p b

输出

(gdb) p a
$1 = {
  _vptr.A = 0x400b40 <vtable for A+16>, 
  a = 0
}
(gdb) p b
$2 = {
  <A> = {
    _vptr.A = 0x400b18 <vtable for B+56>, 
    a = 4196384
  }, 
  members of B: 
  _vptr.B = 0x400af8 <vtable for B+24>, 
  b = 0
}
(gdb) 

我知道_vptr.A和_vptr.B的含义,但我不明白v +对于B + 24或A + 16是什么意思。

感谢您的回答!

2 个答案:

答案 0 :(得分:6)

a的列表表明它是一个包含两个字段的类:一个vptr,指向一个字节,其中A的vtable中包含偏移量16,包含零的数据元素a

第二个是相同的行,但由于虚拟基类而更复杂。它说b由3个字段组成:一个A的实例,其字段与上面的字段类似,然后是B的两个元素,如上所述。这次vptr指向偏移量24。

为什么vptr指向表的中间而不是它的开始?你必须要了解更多关于gcc内存布局细节的信息,我不知道。初始字节可能是RTTI(运行时类型信息),给定的偏移量是虚函数指针数组的第一个元素。有无数的其他选择。

NB。有一些很好的信息in this earlier article表示总有2个指针指向vtable:一个用于多重继承顶部指针,另一个用于RTTI。如果您的机器和编译器是64位(您真的应该提到它;这很重要),这与16个字节的指针重合。 B可以是24个字节,因为有一个额外的指针可以访问虚拟基类。

答案 1 :(得分:0)

从该post引用的

IMO,首先,在B中,您正在使用 virtual 关键字进行隐式阴影处理,这是一种不好的做法,它会在运行时给不同的编译器带来惊喜。

基于64位arch。

<vtable for A+16>表示将A的vtable地址偏移16,这是第一个函数项。按照该帖子的assembly code应用您的代码:

vtable for A:
        .quad   0
        .quad   typeinfo for A
        .quad   A::print() const

一个四边形是4个字,表示8。因此,A::print()的地址是地址(标签)vtable for A加16个偏移量,位于文本部分。

与B相同,这更加复杂,因为您使用的是纯虚拟继承。

vtable for B:
        .quad   16
        .quad   0
        .quad   typeinfo for B
        .quad   B::print() const
        .quad   -16
        .quad   -16
        .quad   typeinfo for B
        .quad   virtual thunk to B::print() const

通常,B仅有一个vtable,如上所示。但是您可以将其视为2个在概念上串联的vtable。

对于B vtable的B部分

vtable for B:
        .quad   16
        .quad   0
        .quad   typeinfo for B
        .quad   B::print() const

对于B vtable的A部分:

        .quad   -16
        .quad   -16
        .quad   typeinfo for B
        .quad   virtual thunk to B::print() const

这就是<vtable for B>+56所指。