是否有任何研究或一组基准测试显示由于在GCC中指定-fno-strict-aliasing(或其他编译器中的等效项)而导致的性能下降?
我面临着关于C++严格别名规则及其可能含义的困惑.请考虑以下代码:
int main() {
int32_t a = 5;
float* f = (float*)(&a);
*f = 1.0f;
int32_t b = a; // Probably not well-defined?
float g = *f; // What about this?
}
Run Code Online (Sandbox Code Playgroud)
看看C++规范,3.10.10节,从技术上讲,没有一个给定的代码似乎违反了给定的"别名规则":
如果程序试图通过以下类型之一以外的左值访问对象的存储值,则行为未定义:
...合格的访问者类型列表...
*f = 1.0f;不会违反规则,因为无法访问存储的值,即我只是通过指针写入内存.我不是从记忆中读书或试图在这里解释一个值.int32_t b = a;不违反规则,因为我通过其原始类型进行访问.float g = *f;出于同样的原因,这条线并没有违反规则.在另一个线程中,成员CortAmmon实际上在响应中提出了相同的点,并且添加了通过写入活动对象而产生的任何可能的未定义行为,如 *f = 1.0f;将在标准的"对象生存期"定义(似乎是对于POD类型来说是微不足道的).
但是:互联网上有大量证据表明上述代码将在现代编译器上产生UB.例如,见这里和这里.
在大多数情况下,论证是编译器可以自由考虑&a,f而不是相互混叠,因此可以自由重新安排指令.
现在最大的问题是,如果这种编译器行为实际上是对标准的"过度解释".
唯一一次标准谈论"混叠"的唯一一次是在3.10.10的脚注中,其中明确指出那些是控制混叠的规则.
正如我之前提到的,我没有看到任何上述代码违反了标准,但是很多人(可能还有编译人员)认为它是非法的.
我真的很感激这里的一些澄清.
小更新:
正如成员BenVoigt指出的那样,int32_t …
c++ memory compiler-construction strict-aliasing type-punning
C++11 §3.8.1 declares that, for an object with a trivial destructor, I can end its lifespan by assigning to its storage. I am wondering if trivial destructors can prolong the object's lifespan and cause aliasing woes by "destroying an object" that I ended the lifespan of much earlier.
To start, something which I know is safe and alias-free
void* mem = malloc(sizeof(int));
int* asInt = (int*)mem;
*asInt = 1; // the object '1' is now alive, trivial constructor + assignment …Run Code Online (Sandbox Code Playgroud)