"<vtable for A+16>"是什么意思?

what does "<vtable for A+16>" mean?

本文关键字:是什么 意思 gt for lt vtable A+16      更新时间:2023-10-16

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

#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的含义,但我不明白B+24或A+16的vtable是什么意思。

谢谢你的回答!

a的列表表明它是一个有两个字段的类:一个vptr指向a的vtable内偏移量为16的字节,另一个数据元素a包含零。

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

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

注:。在前面的文章中有一些很好的信息说,vtable总是有两个指针:一个用于多继承顶部指针,另一个用于RTTI。如果你的机器和编译器是64位的(你真的应该提到这一点;这很重要),这与16字节的指针相一致。B可以是24字节,因为有一个额外的指针来访问虚拟基类。

引用自这篇文章:

IMO,首先,在B中,您在没有virtual关键字的情况下执行隐式阴影,这是一种糟糕的做法,它会在运行时从不同的编译器中给您带来惊喜。

基于64位拱门。

<vtable for A+16>表示将A的vtable地址偏移16,这是第一个函数条目。遵循应用代码的帖子的组装代码:

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

quad是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,如上所示。但您可以将其视为概念上连接的两个vtables。

对于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所指的。