[英]Breaking the strict-aliasing rule in the simplest assignment
在阅读了理解严格的混叠文章https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html之后,我看到了,打破严格混叠规则会如何在优化的构建中导致意外的结果。 例如:
void test(int* ptr1, float* ptr2);
由于ptr1
和ptr2
不兼容,因此编译器假定它们永远不会指向同一内存。 如果指针具有相同的值,则可以优化代码,从而产生意外结果。
但是,在遗留代码中,严格混叠规则通常在简单的分配中就被破坏,例如int n = 0; float f = *((float*)&n);
int n = 0; float f = *((float*)&n);
考虑以下代码:
#include <iostream>
static_assert (sizeof(float) == sizeof(int), "error");
int main(int argc, char *argv[])
{
float f1, f2;
int n = static_cast<int>(argv[1][0] - '0'); // Command argument is "0", so n = 0
memcpy(&f1, &n, sizeof(f1)); // strict-aliasing rule is not broken
f2 = *(reinterpret_cast<float*>(&n)); // strict-aliasing rule is broken
std::cout << f1 << " " << f2 << std::endl; // prints 0 0
return 0;
}
我想知道,C ++编译器甚至有可能生成优化的代码,该代码可以给出不同的f1
和f2
值,这意味着,对于违反严格混淆规则的代码,它给出了意外的结果。
我调查了VC ++ 2015编译器在Debug和Release版本中生成的Assembly代码(为简单起见,使用32位代码)。 在这两种情况下, f2
分配都转换为2条movss
指令,如下所示:
movss xmm0,dword ptr [n]
movss dword ptr [esp+4],xmm0
因此,我了解现代C ++编译器是否会在违规行上给出错误或警告。 但是,如果编译成功,哪种优化的Assembly代码会产生意外结果?
笔记:
此代码有意违反严格混叠规则。
我知道这是UB。
我不问什么是严格混叠规则,我想知道,在这种特定情况下,违反规则会如何导致UB。
一旦有了UB,一切都会发生。
编译器可以在程序中执行任何操作。
一些编译器在检测到UB时会“删除” UB分支,因此您的程序可能不显示任何内容。 这就是为什么在UB上进行推理没有用的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.