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

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:

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值