[英]Different Layouts for the same Type in one Binary
Sometimes C++ compilers generate different memory layouts for the same type T within the same binary. 有时,C ++编译器会在同一二进制文件中为同一类型T生成不同的内存布局。 Namely, this happens when objects occur both as non-contiguous subobject of a class, and as a standalone object or array subobject:
即,当对象同时作为类的非连续子对象和独立对象或数组子对象出现时,会发生这种情况:
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;
According to C++14 standard , is the compiler free to generate any number of different layouts for objects of type T within a single binary? 根据C ++ 14标准 ,编译器是否可以在单个二进制文件中自由地为T类型的对象生成任意数量的不同布局? Are the memory layouts fixed at compile time?
内存布局在编译时是否固定?
Spin-off: How does placement new know which layout to create? 分拆: 新的展示位置如何知道要创建哪个布局?
Elaboration on the second question: An object t of type T may be accessed either by T* or by char* pointers. 详细讨论第二个问题:T *或char *指针可以访问类型T的对象t。 (The latter is justified by §3.10 (10)) Once the compiled program is running, one may determine the relative offsets of subobjects of t by accessing t via char pointers.
(后者由第3.10(10)节证明是正确的)一旦编译的程序运行,就可以通过通过char指针访问t来确定t的子对象的相对偏移。 Are these offsets deterministic, or may they change from one program execution to another?
这些偏移量是确定的,还是可以从一个程序执行更改为另一个程序?
According to C++14 standard you get UB if you convert pointer to a class to pointer to something else and then use the pointer. 根据C ++ 14标准 ,如果将指向类的指针转换为指向其他对象的指针,然后使用该指针,则会得到UB。 So you can't get offset from the class beginning and then add it class pointer.
因此,您无法从类开头获取偏移量,然后将其添加到类指针。
For standard layout objects you get more guarantees and you can use offsetof and get deterministic results. 对于标准布局对象,您可以获得更多保证,并且可以使用offsetof并获得确定性的结果。 Classes with virtual inheritance are tricky thing and are definitely not standard layout ones.
具有虚拟继承的类是棘手的事情,并且绝对不是标准布局的类。
Preliminary answer (As of now, don't take this for granted): 初步答案(截至目前,不要认为这是理所当然的):
Let's assume T is a class type with at least two non-static data members. 假设T是具有至少两个非静态数据成员的类类型。 If T is no standard-layout class, let's assume the two data members are public and private, having different access control.
如果T不是标准布局类,则假定两个数据成员是公共的和私有的,具有不同的访问控制。 It is understood that the layouts described below meet the ordering and contiguity requirements imposed by the standard.
可以理解,下面描述的布局符合该标准规定的顺序和邻接要求。
a) If T is neither trivially copyable nor standard layout, the implementation is free to use a random number generator to create a new memory layout when an object of type T is created. a)如果T既不是普通复制也不是标准布局,则在创建T类型的对象时,实现可以自由使用随机数生成器来创建新的内存布局。 There is no upper limit to the number of different memory layouts for T that may be created by a single binary.
单个二进制文件可能创建的T的不同内存布局的数量没有上限。 (Nothing to the contrary in the standard. really? Must be missing something)
(标准中没有任何相反的地方。真的吗?一定缺少一些东西)
b) If T is trivially copyable, but not standard layout, the implementation is free to use a random number generator at program start to generate a layout for T. The number of possible layouts is finite. b)如果T是可微复制的,但不是标准布局,则实现可以在程序开始时随意使用随机数生成器来生成T的布局。可能的布局数量是有限的。 The layouts may differ from one program execution to the next one.
布局可能从一个程序执行到下一个程序不同。 (restrictions due to §3.9.2 and §1.8.5)
(由于第3.9.2节和第1.8.5节的限制)
c) If T is standard-layout, there is only one possible layout. c)如果T是标准布局,则只有一种可能的布局。 (Order and contiguity guaranteed)
(保证顺序和连续性)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.