Dumping a C++ object’s memory layout with Clang
December 17th, 2012 at 5:25 amWhen one wants to understand the memory layout of structures and classes, the C/C++ operators sizeof and offsetof are very useful. However, when large C++ class hierarchies are involved, using these operators becomes tedious. Luckily, Clang has a very handly command-line flag to dump object layouts in a useful manner. This flag is somewhat hidden since it’s only accepted by the Clang front-end (the one you get when you pass -cc1 to clang) and not the gcc-compatible compiler driver (the one you get when simply executing clang).
Consider this code, for example:
class Base {
protected:
int foo;
public:
int method(int p) {
return foo + p;
}
};
struct Point {
double cx, cy;
};
class Derived : public Base {
public:
int method(int p) {
return foo + bar + p;
}
protected:
int bar, baz;
Point a_point;
char c;
};
int main(int argc, char** argv) {
return sizeof(Derived);
}
To see the layout, run clang -cc1 -fdump-record-layouts myfile.cpp. It will produce a separate report for each class and struct defined, but the most interesting one is for class Derived:
*** Dumping AST Record Layout
0 | class Derived
0 | class Base (base)
0 | int foo
4 | int bar
8 | int baz
16 | struct Point a_point
16 | double cx
24 | double cy
| [sizeof=16, dsize=16, align=8
| nvsize=16, nvalign=8]
32 | char c
| [sizeof=40, dsize=33, align=8
| nvsize=33, nvalign=8]
(the above is the output of Clang 3.2 running on 64-bit Linux)
We can see the layout of Derived objects, with the offset of every field (including the fields coming from base classes) in the left-most column. Some additional information is printed in the bottom – for example, sizeof – the total size, and dsize – data size without tail padding.
If we make method virtual in the Base and Derived classes, the size of the virtual-table pointer is also accounted for:
*** Dumping AST Record Layout
0 | class Derived
0 | class Base (primary base)
0 | (Base vtable pointer)
0 | (Base vftable pointer)
8 | int foo
12 | int bar
16 | int baz
24 | struct Point a_point
24 | double cx
32 | double cy
| [sizeof=16, dsize=16, align=8
| nvsize=16, nvalign=8]
40 | char c
| [sizeof=48, dsize=41, align=8
| nvsize=41, nvalign=8]
I’ll wrap up with a tip about using clang -cc1. Since this isn’t the compiler driver, it won’t go look for standard headers in the expected places, so using it on realistic source files can be a pain. The easiest way to do it, IMHO, is to run it on preprocessed source. How your source gets preprocessed depends on your build process, but it’s usually something like:
clang -E [your -I flags] myfile.cpp > myfile_pp.cpp
Related posts:

December 19th, 2012 at 06:09
If you are using Visual Studio, you can print the same using undocumented /d1reportAllClassLayout switch:
class Derived size(40):+---
| +--- (base class Base)
0 | | foo
| +---
4 | bar
8 | baz
| <alignment member> (size=4)
16 | Point a_point
32 | c
| <alignment member> (size=7)
+---
and second example:
class Derived size(40):+---
| +--- (base class Base)
0 | | {vfptr}
4 | | foo
| +---
8 | bar
12 | baz
16 | Point a_point
32 | c
| <alignment member> (size=7)
+---
Derived::$vftable@:
| &Derived_meta
| 0
0 | &Derived::method
Derived::method this adjustor: 0
December 19th, 2012 at 06:33
To make the output of VC readable use undname.exe to it.
December 26th, 2012 at 06:28
Small typo (how can it be – isn’t this the output of clang ?):
In the first dump [int foo] is shown as [int f]
December 26th, 2012 at 13:52
@Eden,
Fixed, thanks.
January 13th, 2013 at 13:16
Hi Eli,
Very helpful post, thanks. Do you have any idea why “sizeof” is required in order to get the object’s layout? If the class is not instantiated with the “new” keyword, or its size is not checked in the code, its layout won’t be printed at all. For example, the following example succeeds:
The layout of the struct “s” is printed correctly. But this won’t work:
I get no output at all from “clang -cc1 -fdump-record-layouts test.cpp” in this case. Is this a bug in the clang frontend?
January 13th, 2013 at 14:35
@Wilfred,
Good question – I noticed this also. Actually I don’t know the exact cases in which Clang prints out the layout – maybe it makes sense to ask in the cfe-dev list.