使用VS查看类实例的内存布局
因为 MSVC 下使用 /d1 reportAllClassLayout
开关可以很方便的查看内存布局,可以查看虚函数表,内存占用大小等。
其使用方法是:首先确保电脑安装了 VS,我安装的是 VS2019,在 Win10 的开始菜单中依次找到:Visual Studio Tools -> x64 Native Tools Command Prompt for VS 2019 -> 打开,会进入 CMD 界面,然后切换到你的代码目录,比如我的代码在 CppTest 目录下,使用 cd
命令切换:
cd D:\Study\C++\CppTest
使用 dir
命令可以查看该目录下的所有文件,此目录下,我们有一个 CppTest.cpp 文件,其中是 Cpp 关于类的继承的代码。
我们输入命令:cl /d1 reportSingleClassLayoutXXX [filename]
,其中 XXX
是类名,[filename]
是文件名,实例如下,比如类名是 D,文件是 CppTest.cpp :
cl /d1 reportSingleClassLayoutD CppTest.cpp
输出结果中可能打印出了很多类的信息,但前面很多都是标准库中的调用类相关,我们不用关心,只需要在后面找到我们编写的类 D 的内存布局即可,例如现在有 cpp 代码中类 D 定义如下:
class Base
{
public:
virtual void fun(){ cout << "This is Base::fun()" << endl; }
private:
int num;
};
class D : public Base
{
public:
void fun(){ cout << "This is D::fun()" << endl; }
};
我们关心的是 D 类,从结果中找到 D 类对应的内存布局如下:
class D size(16):
+---
0 | +--- (base class Base)
0 | | {vfptr}
8 | | num
| | <alignment member> (size=4)
| +---
+---
D::$vftable@:
| &D_meta
| 0
0 | &D::fun
D::fun this adjustor: 0
从中可以直观的看出:虚函数表及布局,类的大小,类成员占用大小,成员相较于起始地址的偏移量,字节对其信息。这将对我们分析类继承中的虚基类表和虚函数表的内存布局和内存占用有很大的帮助。
可以看到 MSVC 编译器将虚函数表指针放在了内存的开始处(对象存储空间的开始位置)(因为地址偏移量是0),然后才是成员变量。下面还有虚函数表的信息,紧跟在 &XXX_meta
其中 XXX
是类名,下面还有一个 0,表示这张虚函数表对应的虚指针在内存中的分布,下面列出了虚函数,其左侧的 0 表示的是虚函数的序号,并不是和上面的类的内存布局左侧的数字 8 一样表示的是相较于起始内存地址的偏移量,因为这里是有一个虚函数,如果有多个虚函数,其序号将依次为 0,1,2 … 等,这个方法将在另外的篇幅中讲述虚函数表和虚基类表时非常有用。