Dumping a C++ object's memory layout with Clang

来源:互联网 发布:郑州网络维修 编辑:程序博客网 时间:2024/06/05 03:05

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++ operatorssizeof 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 executingclang).

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 forclass 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
0 0
原创粉丝点击