2016-10-06 71 views
1

有時C++編譯器爲同一個二進制文件中的同一類型T生成不同的內存佈局。即,這種情況發生時發生的對象的類的既作爲非連續子對象,和作爲一個獨立的對象或數組子對象:一個Binary中同一類型的不同佈局

struct A { int i; }; 
struct B : virtual A { int i; }; 
struct C : virtual A { int i; }; 
struct D : B,C { int i; }; 
... 
D d; 
B b; 
B* p1= &(B&)d; 
B* p2= &b; 

根據C++ 14標準,可以自由地產生任何編譯器單個二進制文件中T類型對象的不同佈局的數量? 內存佈局是否在編譯時固定?

分拆:How does placement new know which layout to create?


精化對第二個問題: 類型T的對象噸可通過T *或由字符*指針來訪問。 (後者由§3.10(10)證明)編譯好的程序一旦運行,就可以通過char指針訪問t來確定t的子對象的相對偏移量。這些偏移量是確定性的,還是可能從一個程序執行到另一個程序執行?

+0

你能否詳細說明你的問題?你是什​​麼意思*在編譯時內存佈局是否固定*? –

回答

2

根據C++ 14標準,如果將指針轉換爲指向其他指針的指針,然後使用指針,則會得到UB。所以你不能從類開始偏移,然後添加類指針。

對於標準佈局對象,您可以獲得更多保證,您可以使用offsetof並獲得確定性結果。具有虛擬繼承的類是棘手的事情,絕對不是標準的佈局類。

+0

您能否提供支持您的UB索賠的報價?雖然有一些演員會導致UB,但我認爲這樣做沒問題。 ((char *)(void *)&t) –

+0

演員本身很好。您可以將任何指針轉換爲任何指針(注意:在Visual Studio指針中虛擬繼承的類的方法更大)。但是你可以用這種鑄造指針做的唯一事情就是複製它,或者將它轉換回原來的類型。 UB不在鑄造指針中,而是在類佈局上的假設,即實現細節。 –

+0

你的意思是UB =未定義或未指定?現在,將隨機的隨機數字寫入文件顯然是不明確的,寫入原始內存並不是那麼簡單。 (這個標準非常清楚它談論的是一個非確定性的抽象機器)我不知道它會在哪裏降級到未定義的行爲,從而導致整個程序失效。該標準指定* p表示字符指針p的含義。 (§5.3.1.1,§3.10.10) –

0

初步的答案(截至目前,不走這是理所當然的):

假設T是一個類類型至少有兩個非靜態數據成員。如果T不是標準佈局類,讓我們假設這兩個數據成員是公共和私有的,具有不同的訪問控制。可以理解的是,下面描述的佈局符合該標準施加的排序和鄰接要求。 a)如果T不是普通可複製的,也不是標準佈局,當創建T類型的對象時,實現可以隨意使用隨機數生成器來創建新的內存佈局。 T可能由單個二進制創建的不同內存佈局的數量沒有上限。 (在標準中沒有什麼相反的,真的嗎?必須缺少一些東西)

b)如果T是普通可複製的,但不是標準佈局,則實現可以在程序開始時隨意使用隨機數生成器來生成佈局爲T.可能的佈局數量是有限的。從一個程序執行到下一個程序執行,佈局可能不同。 (由§3.9.2和§1.8.5引起的限制)

c)如果T是標準佈局,則只有一種可能的佈局。 (訂單和連續保證)

相關問題