After reading the Understanding Strict Aliasing article https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html I see, how breaking the strict-aliasing rules can cause unexpected results in optimized build. For example:
void test(int* ptr1, float* ptr2);
Since ptr1
and ptr2
are incompatible, compiler assumes that they will never point to the same memory. This allows to optimize the code, which can give unexpected results, if pointers have the same value.
However, in legacy code strict-aliasing rule is mostly broken in simple assignments, like int n = 0; float f = *((float*)&n);
Consider the following code:
#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;
}
I wonder, how it is even possible for C++ compiler to produce an optimized code, which can give different f1
and f2
values, this means, give unexpected result for the code that breaks strict-aliasing rule.
I investigated Assembly code produced by VC++ 2015 compuler in Debug and Release builds (for simplicity, in 32 bit code). In both cases, f2
assignment is converted to 2 movss
instructions, like this:
movss xmm0,dword ptr [n]
movss dword ptr [esp+4],xmm0
So, I understand if modern C++ compiler will give an error or warning on the offending line. But if compilation is successful, what optimized Assembly code can give an unexpected result?
Notes:
This code intentionally breaks the strict-aliasing rule.
I know that this is UB.
I don't ask what is the strict-aliasing rule, I want to know, how breaking the rule can cause UB in this specific case.