c++ - GCC中vtable的第一个地址?
问题描述
当我构建、拆解和清理这个短程序时:
struct Base {
virtual int compute() { return 42; }
};
struct Derived: public Base {
int compute() override { return 23; }
};
int main() {
Base* a = new Derived;
a->compute();
}
我用一些自制的魔法来做:
g++ -g -o- -S foo.cpp | \
c++filt | \
perl -pe 's/^\.LA\w+:\r?\n//gm' | \
perl -0777 -pe 's/^\.Ldebug\w+:\r?\n(\s+\..+?\r?\n)+//gm' | \
perl -pe 's/^\.L\w+:\r?\n//gm' | \
perl -pe 's/^\s+\.(align|section|weak|loc|file|cfi).+\r?\n//gm' | \
highlight --out-format=ansi --syntax=asm
我明白了:
vtable for Derived:
.quad 0
.quad typeinfo for Derived
.quad Derived::compute()
.type vtable for Base, @object
.size vtable for Base, 24
vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::compute()
.type typeinfo for Derived, @object
.size typeinfo for Derived, 24
我注意到我vtable
的结构如下:
0. ???
1. Pointer to typeinfo
2. Pointer to first virtual method
3. Pointer to second virtual method
4. ...
我不明白0
atvtable[0]
是什么,但是在发现了这个其他SO 问题之后,我写了另一个例子来理解这个偏移量。
这个使用虚拟继承。
struct Top {
virtual void foo() { }
};
struct Left: public Top { // note: non virtual
void foo() override { }
};
struct Right: virtual public Top {
void foo() override { }
};
// note: Bottom is not a "diamond", Top is base twice
struct Bottom: public Left, public Right {
void foo() override { }
};
int main() {
Bottom bottom;
bottom.foo();
}
这次我的vtable
样子是这样的:
vtable for Bottom:
.word 4
.word 0
.word typeinfo for Bottom
.word Bottom::foo()
.word 0
.word -4
.word -4
.word typeinfo for Bottom
.word non-virtual thunk to Bottom::foo()
所以我能够解释第一个0
变成 的4
,但我仍然无法解释我的 vtable 的新结构。
我正在寻找一个更详细的答案来解释后一个例子。
解决方案
推荐阅读
- symfony - 如何使用 symfony/webpack-encore 缩小 CSS/JS 文件?
- firebase - 如何使用 Firebase 存储在 Flutter 应用中上传和下载 pdf 文件
- vb.net - VB.NET 2008 或更高版本:通过 winapi 读取 STDIN 的内存冲突
- javascript - Webpack devserver 代理无法解决 CORS 问题
- c# - C# - Google Sheets API,如何在单元格中检索图像位置?
- php - 在 PHP 中将最后一位数字舍入为 0 、 5 或 9
- python - 如何从字典中的键中获取特定值,每个键有多个值?
- sql - 替换加入只留下一个“表扫描”
- node.js - Node.js 按位 OR 停止为大数字工作
- xamarin.forms - 样式化和重新启动应用程序