Нарушение правила строгого наложения в простейшем задании - PullRequest
0 голосов
/ 07 ноября 2018

После прочтения статьи Понимание строгого алиасинга 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 ++ выдаст ошибку или предупреждение в ошибочной строке. Но если компиляция прошла успешно, какой оптимизированный код сборки может дать неожиданный результат?

Примечания:

  1. Этот код намеренно нарушает правило строгого наложения имен.

  2. Я знаю, что это UB.

  3. Я не спрашиваю, что такое правило строгого наложения имен, я хочу знать, как нарушение правила может вызвать UB в этом конкретном случае.

1 Ответ

0 голосов
/ 07 ноября 2018

Если у вас есть UB, все может произойти.

Компилятору разрешено делать все что угодно в вашей программе.

Некоторые компиляторы «удаляют» ветку UB при обнаружении UB, поэтому ваша программа может ничего не отображать, например. Вот почему рассуждения о UB бесполезны.

...