使用CL編譯器選項檢視C 類記憶體布局 轉

2021-08-05 18:17:57 字數 3927 閱讀 3170

今天查資料的時候發現 vs 編譯器 cl 的乙個編譯選項可以檢視 c++ 類的記憶體布局,非常有用。使用如下,從開始程式選單找到 visual stdio 2008/2005 command prompt,選擇 vs 的命令列工具,按如下格式使用:

>cl –d1reportsingleclasslayout[classname]  test.cpp

而使用 –d1reportallclasslayout 則可以檢視原始檔中所有類及結構體的記憶體布局。

其中,classname 為類名,-d1reportsingleclasslayout[classname] 之間沒有空格。編寫程式測試:

比較奇怪,加上 #include 後,測試結構體的時候就會出現很輸出,應該是庫中的類,看起來真麻煩,所以這裡去掉它。

1: 

//test: >cl test.cpp /d1reportsingleclasslayout[classname]

2: 

//#include

3: 

4: 

//using namespace std;

5: 

6: 

struct s

7: ;
12: 

class testclass

13: ;
19: 

//base

20: 

class base

21: ;
28: 

//derived

29: 

class derived: public base

30: ;
36: 

//derived2

37: 

class derived2: public base

38: ;
46: 

//

47: 

class base2

48: ;
54: 

//多重繼承

55: 

class derived3: public base, public base2

56: ;
62: 

//

63: 

int main()

64:
//測試,1:測試結構體 s:>cl test.cpp /d1reportsingleclasslayouts

可以看到,vc 預設情況下,結構體內使用位元組對齊,char x, 和 int y 之間填充了 3 個位元組的空間。預設情況,vc 對結構體內的位元組按最大位元組對齊,成員變數之間的順序不同,結構體所佔空間也可能不同。

2. 測度類 testclass: >cl test.cpp /d1reportsingleclasslayouttestclass

同樣可以看到,類 testclass 中資料成員的按最大資料成員位元組對齊,char y 和 double z 之間插入了 7 個位元組,double z 和 int x 之間插入了 4 個位元組,按 double 型對齊,32 位機器上, sizeof(double) = 8。

3.測試有虛函式的類 base: >cl test.cpp /d1reportsingleclasslayoutbase

其中是虛函式表,可以看到,vc 將虛函式表位址放在了物件的頭 4 個位元組,接著才是資料成員。虛函式表是乙個陣列,裡面存放的是類中虛函式的位址,可以看到虛函式成員的位址是按照宣告的順序存放的。

4.測試子類 derived:>cl test.cpp /d1reportsingleclasslayoutderived

可以看到,基類的虛函式存放在虛表的前面,子類中自己宣告的虛函式按順序存放在後面。

5.測試子類derived2: >cl test.cpp /d1reportsingleclasslayoutderived2

可以看到,子類 derived2 中重寫了基類 base 中的虛函式 f1(),因此 devried2 的虛表中 f1() 的位置被 derived2 重寫的 f1() 代替,因此便實現了多型。非虛函式位址不存放在虛表中。

6.測試多重繼承的類derived3: >cl test.cpp /d1reportsingleclasslayoutderived3

可以看到vc中對多重繼承的處理,子類 derived3 的物件中,前 4 個位元組存放的是第乙個基類的 虛表,然後是第乙個基類的資料成員。接著是第 2 個基類的虛表及資料成員。最後才是自己的資料成員。其中,derived3::$vftable@base2@: -8, -8 表示第 2 個基類相對於虛表相對於 derived3 的偏移量 offset。

//測試結構體的位元組對齊,以及 #pragma pack(1), offsetof(struct,number) 的用法。

1: #include
2: 

3: 

using

namespace std;

4: 

5: 

struct st1

6: ; //20

13: 

14: 

struct st2

15: ;//16

22: 

23: 

#pragma pack(1)

24: 

struct st3

25: ; //15

32: 

#pragma pack()

33: 

34: 

void testsizeof()

35:
61: 

int main()

62:
其中,vc對結構體中的資料成員預設按照最大成員對齊,#pragma pack(num) 可以設定對齊位元組數,可以為1、2、4、8、16 。也可以使用編譯選項 /zp[1|2|4|8|16] 修改對齊方式,取消修改用#pragma pack(),如果結構體某成員的 sizeof 大於你設定的,則按你的設定來對齊。注意 offsetof 的用法,可以很容易觀察結構體的內部結構

還可以使用前面所說的 cl –d1reportsingleclasslayout[classname]  test.cpp 編譯選項進行相互驗證。

微軟cl編譯器的簡單使用

cl的位置 開始 所有程式 microsoft visual studio visual studio tools developer command prompt 編譯器產生通用物件檔案格式 coff 物件 obj 檔案。鏈結器產生可執行檔案 exe 或動態鏈結庫檔案 dll 注意,所有編譯器選項...

微軟cl編譯器的簡單使用

cl的位置 開始 所有程式 microsoft visual studio visual studio tools developer command prompt 編譯器產生通用物件檔案格式 coff 物件 obj 檔案。鏈結器產生可執行檔案 exe 或動態鏈結庫檔案 dll 注意,所有編譯器選項...

VS 使用cl檢視c 物件記憶體模型

編寫 如下,檔案命名為cpptest.cpp class div int main 我使用的是win7 64位作業系統,vs2015,可以在開始 所有程式 visual studio 2015 visual studio tools中啟動vs2015開發人員命令提示,如下圖 或者開啟cl.exe程式...