Dumping a C++ object's memory layout with Clang
2015-12-13 09:26
405 查看
http://eli.thegreenplace.net/2012/12/17/dumping-a-c-objects-memory-layout-with-clang
When 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:
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:
(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:
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:
When 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
相关文章推荐
- Windows Clang开发环境备忘
- [转载]Visual Studio, GCC, Clang, Intel 对 C++11 特性的支持一览表
- vim c/c++智能补全插件
- Ubuntu下clang开发工具简易入门知识(一)
- pip install MySQL-python error in virtualenv on mac
- llvm+clang的安装(使用cmake)
- Ubuntu 12.04 上配置ios开发环境搭建
- CLang之简单介绍
- 静态代码扫描学习
- SUSE Linux Enterprise 11 SP3 成功编译LLVM + Clang 3.4
- Malloc size的大小
- iOS 警告收录及科学快速的消除方法
- 利用clang提供的库函数进行c语言常规错误的检测
- Ubuntu下clang开发工具简易入门知识(一)
- linux下clang+llvm3.3安装(ubuntu)
- 关于Mac中库文件和包含文件搜索路径
- clang: error: no such file or directory:xxx的处理方法
- IOS客户端静态扫描持续集成搭建
- the first try for clang