【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,內容示例:spa

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,相似code

*** 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

添加編譯選項blog

/d1reportSingleClassLayout<類名> :輸出單個類相關佈局繼承

seo

/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\n", sizeof(void*));                        

    printf("X: %lu\n", sizeof(X));                              
    printf("Y: %lu\n", sizeof(Y));                                                                 
    printf("Z: %lu\n", sizeof(Z));                              
    printf("A: %lu\n", sizeof(A));                              

return 0; }
相關文章
相關標籤/搜索