使用编译器查看类的内存布局

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// main.cpp
class Base
{
protected:
int n;

public:
int foo(int p)
{
return n + p;
}

virtual int bar(int p){
return n + p;
}
};

struct Point
{
double cx, cy;
};

class Derived : public Base
{
public:
int foo(int p)
{
return n + a + p;
}

protected:
int a, b;
Point a_point;
char c;
};

int main(int argc, char **argv)
{
return sizeof(Derived);
}

msvc

命令格式:

  • 查看单个类的内存布局: cl <FileName> /d1reportSingleClassLayout[ClassName]
  • 查看所有类的内存布局: cl <FileName> /d1reportAllClassLayout

使用 cl 查看单个类的内存布局:

1
cl main.cpp /d1reportSingleClassLayoutDerived > msvc.txt

输出内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
main.cpp

class Derived size(40):
+---
0 | +--- (base class Base)
0 | | {vfptr}
4 | | n
| +---
8 | a
12 | b
16 | Point a_point
32 | c
| <alignment member> (size=7)
+---

Derived::$vftable@:
| &Derived_meta
| 0
0 | &Base::bar
Microsoft (R) Incremental Linker Version 14.29.30151.0
Copyright (C) Microsoft Corporation. All rights reserved.

/out:main.exe
main.obj

参考:https://www.gonwan.com/2010/09/20/c-class-layout-using-msvc/

gcc

命令格式:

  • gcc8 之前:gcc -fdump-class-hierarchy <FileName>
  • gcc8 之后:gcc -fdump-lang-class <FileName>

使用例子:

1
gcc -fdump-lang-class main.cpp

输出的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Vtable for Base
Base::_ZTV4Base: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4Base)
16 (int (*)(...))Base::bar

Class Base
size=16 align=8
base size=12 base align=8
Base (0x0x7fcb184c8420) 0
vptr=((& Base::_ZTV4Base) + 16)

Class Point
size=16 align=8
base size=16 base align=8
Point (0x0x7fcb184c8540) 0

Vtable for Derived
Derived::_ZTV7Derived: 3 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 (int (*)(...))Base::bar

Class Derived
size=48 align=8
base size=41 base align=8
Derived (0x0x7fcb18374208) 0
vptr=((& Derived::_ZTV7Derived) + 16)
Base (0x0x7fcb184c85a0) 0
primary-for Derived (0x0x7fcb18374208)

参考:

https://stackoverflow.com/questions/2979606/print-layout-of-c-object-with-g-compiler

https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Developer-Options.html

clang

命令格式:clang -cc1 -fdump-record-layouts <FileName>

使用例子:

1
clang -cc1 -fdump-record-layouts main.cpp > clang.txt

输出内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

*** Dumping AST Record Layout
0 | class Base
0 | (Base vtable pointer)
8 | int n
| [sizeof=16, dsize=12, align=8,
| nvsize=12, nvalign=8]

*** Dumping AST Record Layout
0 | struct Point
0 | double cx
8 | double cy
| [sizeof=16, dsize=16, align=8,
| nvsize=16, nvalign=8]

*** Dumping AST Record Layout
0 | class Derived
0 | class Base (primary base)
0 | (Base vtable pointer)
8 | int n
12 | int a
16 | int b
24 | struct Point a_point
24 | double cx
32 | double cy
40 | char c
| [sizeof=48, dsize=41, align=8,
| nvsize=41, nvalign=8]

参考:
https://eli.thegreenplace.net/2012/12/17/dumping-a-c-objects-memory-layout-with-clang/