gpt4 book ai didi

c++ - 虚拟继承表在 g++ 中是如何工作的?

转载 作者:太空宇宙 更新时间:2023-11-04 12:10:47 24 4
gpt4 key购买 nike

我试图更好地理解虚拟继承在实践中是如何工作的(也就是说,不是根据标准,而是在像 g++ 这样的实际实现中)。实际问题在底部,以粗体显示。

因此,我为自己构建了一个继承图,其中包含以下简单类型:

struct A {
unsigned a;
unsigned long long u;
A() : a(0xAAAAAAAA), u(0x1111111111111111ull) {}
virtual ~A() {}
};

struct B : virtual A {
unsigned b;
B() : b(0xBBBBBBBB) {
a = 0xABABABAB;
}
};

(在整个层次结构中我还有一个C: virtual ABC: B,C,这样虚拟继承才有意义。)

我写了几个函数来转储实例的布局,获取 vtable 指针并打印前 6 个 8 字节值(任意以适应屏幕),然后转储对象的实际内存。这看起来像这样:

转储一个 A 对象:

actual A object of size 24 at location 0x936010
vtable expected at 0x402310 {
401036, 401068, 434232, 0, 0, 0,
}
1023400000000000aaaaaaaa000000001111111111111111
[--vtable ptr--]

转储一个B对象和A对象所在的位置,通过在相应位置打印很多A来指示。

actual B object of size 40 at location 0x936030
vtable expected at 0x4022b8 {
4012d2, 40133c, fffffff0, fffffff0, 4023c0, 4012c8,
}
b822400000000000bbbbbbbb00000000e022400000000000abababab000000001111111111111111
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (offset: 16)

如您所见,BA 部分位于 16 字节到 开头的偏移处B 对象(如果我实例化了 BC 并将其动态转换为 B*!,它可能会有所不同)。

我原以为 16(或至少 2,由于对齐)出现在表格中的某处,因为程序必须在运行时查找 A 的实际位置(偏移量)。 那么,布局到底是什么样子的?


编辑:转储是通过调用 dumpdumpPositions 完成的:

using std::cout;
using std::endl;

template <typename FROM, typename TO, typename STR> void dumpPositions(FROM const* x, STR name) {
uintptr_t const offset {reinterpret_cast<uintptr_t>(dynamic_cast<TO const*>(x)) - reinterpret_cast<uintptr_t>(x)};
for (unsigned i = 0; i < sizeof(FROM); i++) {
if (offset <= i && i < offset+sizeof(TO))
cout << name << name;
else
cout << " ";
}
cout << " (offset: " << offset << ")";
cout << endl;
}
template <typename T> void hexDump(T const* x, size_t const length, bool const comma = false) {
for (unsigned i = 0; i < length; i++) {
T const& value {static_cast<T const&>(x[i])};
cout.width(sizeof(T)*2);
if (sizeof(T) > 1)
cout.fill(' ');
else
cout.fill('0');
cout << std::hex << std::right << (unsigned)value << std::dec;
if (comma)
cout << ",";
}
cout << endl;
}
template <typename FROM, typename STR> void dump(FROM const* x, STR name) {
cout << name << " object of size " << sizeof(FROM) << " at location " << x << endl;
uintptr_t const* const* const vtable {reinterpret_cast<uintptr_t const* const*>(x)};
cout << "vtable expected at " << reinterpret_cast<void const*>(*vtable) << " {" << endl;
hexDump(*vtable,6,true);
cout << "}" << endl;
hexDump(reinterpret_cast<unsigned char const*>(x),sizeof(FROM));
}

最佳答案

答案实际上记录在这里,在 Itanium ABI 中.特别是第 2.5 节包含虚拟表的布局。

关于c++ - 虚拟继承表在 g++ 中是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9947805/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com