结果说12。
该函数foobar存储在内存中的什么位置?
#include <iostream>
using namespace std;
struct ABC_ {
int a;
int b;
int c;
int foobar(int a) {
return a;
}
};
int main() {
ABC_ ABC;
cout << sizeof ABC;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该函数存储在.text段内。
\n\n\n编译后的程序\xe2\x80\x99的内存分为五个段:文本段、数据段、bss段、堆段和堆栈段。每个段代表为特定目的而留出的特殊内存部分。文本段有时也称为代码段。这是程序的汇编机器语言指令所在的位置。
\n
对象本身的内存布局是:
\n\nclass ABC_ {\npublic:\n int a; // 0x4 (4)\n int b; // 0x8 (8)\n int c; // 0xC (12)\n int foobar(int a) { // you can print address using &foobar\n return a;\n }\n};\nRun Code Online (Sandbox Code Playgroud)\n\n当你的类包含虚函数时,它们以相同的方式存储,但类的内存布局发生变化...它将有一个不可见的 4 字节(32 位)指针,指向虚函数表或虚方法表/ VMT(此table 只是保存函数的地址以允许多态性,这样的表是为每个类单独创建的,当它继承另一个表时存储在内存中),因此在这种情况下大小将为 16。它还取决于编译器的对齐设置。 ..
\n\n如果你想获取指向 vtable 的指针,可以这样做:
\n\nvoid **get_vtable(void *obj) {\n return *(void ***)obj;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在我所知道的每个编译器中,Vtable 通常存储在开头。
\n\n通过查看函数的调用方式,您可以注意到函数为虚拟函数和非虚拟函数时的差异。普通函数是直接调用/跳转的,但虚拟函数是通过存储在其表中的函数指针来调用的。
\n\n(我脑子里有些x86 asm,可能是错的)
\n\nmov edx, [ecx] // ecx = this pointer\nadd edx, 12h // let's say 0x12 is the offset divided by 4 is 4 = index in vtable\ncall edx // you know it's virtual function\nRun Code Online (Sandbox Code Playgroud)\n\n或者简单地
\n\nmov edx, [ecx+12h]\ncall edx\nRun Code Online (Sandbox Code Playgroud)\n\n了解事物如何存储在内存中的最佳方法是使用一些反汇编器和/或调试器。我推荐 IDA Pro 和 x64dbg。
\n| 归档时间: |
|
| 查看次数: |
2321 次 |
| 最近记录: |