После прочтения статьи Понимание строгого алиасинга 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);
Рассмотрим следующий код:
#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 (для простоты, в 32-битном коде). В обоих случаях назначение f2
преобразуется в инструкции 2 movss
, например:
movss xmm0,dword ptr [n]
movss dword ptr [esp+4],xmm0
Итак, я понимаю, что современный компилятор C ++ выдаст ошибку или предупреждение в ошибочной строке. Но если компиляция прошла успешно, какой оптимизированный код сборки может дать неожиданный результат?
Примечания:
Этот код намеренно нарушает правило строгого наложения имен.
Я знаю, что это UB.
Я не спрашиваю, что такое правило строгого наложения имен, я хочу знать, как нарушение правила может вызвать UB в этом конкретном случае.