zoukankan      html  css  js  c++  java
  • 【C++对象模型】使用gcc、clang和VC++显示C++类的内存布局

    引言

    各种C++实现对C++类/对象的内存布局可能有所不同,包括数据成员的顺序、虚函数表(virtual table: vtbl)的结构、继承关系的处理等。了解C++类/对象的布局,对于理解C++各种机制,正确合理地进行设计和开发有很大的帮助。

    主流编译器的支持

    本文所述的3款主流编译器都提供打印/导出C++类/对象的内存布局的功能,现用表格列出其特性和用法,测试用的代码文件列于文后(data.cpp)

    编译器及验证版本 用法 说明
    gcc 4.8.4 gcc --fdump-class-hierarchy data.cpp

    导出的布局图示在data.cpp同一目录下的一个.class文件中,

    如data.cpp.002t.class,内容示例:

    VTT for A
    A::_ZTT1A: 4u entries
    0 ((& A::_ZTV1A) + 24u)
    8 ((& A::_ZTC1A0_1Y) + 24u)
    16 ((& A::_ZTC1A8_1Z) + 24u)
    24 ((& A::_ZTV1A) + 48u)

    Class A
    size=16 align=8
    base size=16 base align=8
    A (0x0x7f9dbc60c540) 0
    vptridx=0u vptr=((& A::_ZTV1A) + 24u)
    Y (0x0x7f9dbc5c11a0) 0 nearly-empty
    primary-for A (0x0x7f9dbc60c540)
    subvttidx=8u
    X (0x0x7f9dbc5ccae0) 0 empty virtual
    vbaseoffset=-24
    Z (0x0x7f9dbc5c1208) 8 nearly-empty
    subvttidx=16u vptridx=24u vptr=((& A::_ZTV1A) + 48u)
    X (0x0x7f9dbc5ccae0) alternative-path

    clang 3.4 clang -Xclang -fdump-record-layouts data.cpp

     要求data.cpp中有对相关类做sizeof求值的语句,输出在stdout,类似

    *** Dumping AST Record Layout
    0 | class A
    0 | class Y (primary base)
    0 | (Y vtable pointer)
    8 | class Z (base)
    8 | (Z vtable pointer)
    0 | class X (virtual base) (empty)
    | [sizeof=16, dsize=16, align=8
    | nvsize=16, nvalign=8]

    VC++ 2010

    添加编译选项

    /d1reportSingleClassLayout<类名> :输出单个类相关布局

    /d1reportAllClassLayout: 输出所有类相关布局

     编译时输出在“输出”窗口中,类似如下:

    1> class A size(8):
    1> +---
    1> | +--- (base class Y)
    1> 0 | | {vbptr}
    1> | +---
    1> | +--- (base class Z)
    1> 4 | | {vbptr}
    1> | +---
    1> +---
    1> +--- (virtual base X)
    1> +---
    1>
    1> A::$vbtable@Y@:
    1> 0 | 0
    1> 1 | 8 (Ad(Y+0)X)
    1>
    1> A::$vbtable@Z@:
    1> 0 | 0
    1> 1 | 4 (Ad(Z+0)X)

    测试所用代码文件

    data.cpp

    #include <cstdio>
    
    class X {};                                                     
    class Y : public virtual X {};                                  
    class Z : public virtual X {};                                  
    class A : public Y, public Z {};                                
    
    int main(int argc, char** argv)                                 
    {                      
        printf("Ptr: %lu
    ", sizeof(void*));                        
    
        printf("X: %lu
    ", sizeof(X));                              
        printf("Y: %lu
    ", sizeof(Y));                                                                 
        printf("Z: %lu
    ", sizeof(Z));                              
        printf("A: %lu
    ", sizeof(A));                              

    return 0; }
  • 相关阅读:
    Dns信息收集
    Top命令--性能
    一些php常用函数积累
    样本组成了整体,特例装裱了样本
    Android OKHttp 可能你从来没用过的拦截器 【实用推荐】
    一篇文章搞懂android存储目录结构
    [ES6 系列] 你真的了解ES6吗(一)
    撸了一个简易的工具库: jeasy
    SQL基础语句(详解版)
    状态管理之 Flux、Redux、Vuex、MobX(概念篇)
  • 原文地址:https://www.cnblogs.com/zzqcn/p/4742295.html
Copyright © 2011-2022 走看看