不使用由place new返回的指针时的C ++严格别名 [英] C++ strict aliasing when not using pointer returned by placement new
问题描述
这可能会导致不确定的行为吗?
Can this potentially cause undefined behaviour?
uint8_t storage[4];
// We assume storage is properly aligned here.
int32_t* intPtr = new((void*)storage) int32_t(4);
// I know this is ok:
int32_t value1 = *intPtr;
*intPtr = 5;
// But can one of the following cause UB?
int32_t value2 = reinterpret_cast<int32_t*>(storage)[0];
reinterpret_cast<int32_t*>(storage)[0] = 5;
char
具有用于严格混叠的特殊规则.如果我使用char
而不是uint8_t
,它仍然是未定义行为吗?还有什么变化?
char
has special rules for strict-aliasing. If I use char
instead of uint8_t
is it still Undefined Behavior? What else changes?
正如DeadMG成员指出的那样,reinterpret_cast
是依赖于实现的.如果我改用C样式的强制转换(int32_t*)storage
,会发生什么变化?
As member DeadMG pointed out, reinterpret_cast
is implementation dependent. If I use a C-style cast (int32_t*)storage
instead, what would change?
推荐答案
由new放置返回的指针与引入别名考虑时的其他任何指针一样,都是UB引起的.您有责任确保放置对象的内存不会被不应有的别名所混淆.
The pointer returned by placement new can be just as UB-causing as any other pointer when aliasing considerations are brought into it. It's your responsibility to ensure that the memory you placed the object into isn't aliased by anything it shouldn't be.
在这种情况下,您不能假定uint8_t
是char
的别名,因此应用了特殊的别名规则.另外,使用uint8_t
而不是char
数组将毫无意义,因为sizeof()
是用char
而不是uint8_t
表示的.您必须自己计算大小.
In this case, you cannot assume that uint8_t
is an alias for char
and therefore has the special aliasing rules applied. In addition, it would be fairly pointless to use an array of uint8_t
rather than char
because sizeof()
is in terms of char
, not uint8_t
. You'd have to compute the size yourself.
此外,reinterpret_cast
的作用完全是实现定义的,因此代码肯定没有明确定义的含义.
In addition, reinterpret_cast
's effect is entirely implementation-defined, so the code certainly does not have a well-defined meaning.
要实现低级的令人不快的内存hack,原始内存仅需由char*
,void*
和T*
别名,其中T
是最终的目标类型-在这种情况下为int
,以及从T*
可以得到的其他任何内容,例如T
是派生类,并且将派生类的指针转换为指向基数的指针.任何其他情况都违反了严格的别名和鼻恶魔.
To implement low-level unpleasant memory hacks, the original memory needs to be only aliased by char*
, void*
, and T*
, where T
is the final destination type- in this case int
, plus whatever else you can get from a T*
, such as if T
is a derived class and you convert that derived class pointer to a pointer to base. Anything else violates strict aliasing and hello nasal demons.
这篇关于不使用由place new返回的指针时的C ++严格别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!