Описание тега strict-aliasing

Строгий псевдоним - это сделанное компилятором C или C++ допущение, что указатели разыменования объектов разных типов никогда не будут ссылаться на одно и то же место в памяти (т.е. они не будут использовать псевдонимы друг для друга).

Строгий псевдоним - это сделанное компилятором C или C++ допущение, что указатели разыменования объектов разных типов никогда не будут ссылаться на одно и то же место в памяти (т.е. они не будут использовать псевдонимы друг для друга).

Строгий псевдоним или "строгое правило псевдонима" - неофициальные термины. Это относится не к одному, а к набору правил, касающихся совместимости типов при доступе к значению через указатели.

"Строгое нарушение псевдонима" - это когда к значению обращаются через указатель, несовместимый с типом данных. Пример:

short array[2];
int* ptr = (int*)array;       // strict aliasing violation
if(*ptr == something)         // therefore, this is undefined behavior

Здесь подробно объясняется строгий псевдоним: Что такое правило строгого псевдонима?

Причина, по которой существует строгий псевдоним, - это производительность, как обсуждается здесь. Компилятор, который предполагает, что соблюдается строгое правило псевдонима, может выполнять различные оптимизации для повышения производительности.

Традиционно не многие компиляторы выполняли такую ​​оптимизацию, и поэтому неопределенное поведение, вызванное строгими нарушениями псевдонимов, является распространенной неактивной ошибкой во многих программах - ошибкой, которая не появится до тех пор, пока программа не будет перенесена в компилятор, который использует такие оптимизации.

В частности, известно, что компилятор GCC часто выполняет такую ​​оптимизацию. Они автоматически включаются с параметрами компилятора-O2, -O3 or -Os, или явно с -fstrict-aliasing. Строгую оптимизацию псевдонимов можно отключить с помощью-fno-strict-aliasing. Ссылка GCC.


Правила алиасинга описаны в следующих разделах стандартов:

C11 6.5 §7

Сохраненное значение объекта должно быть доступно только выражению lvalue, которое имеет один из следующих типов:
- тип, совместимый с эффективным типом объекта,
- квалифицированная версия типа, совместимая с эффективным типом объекта,
- тип, который представляет собой знаковый или беззнаковый тип, соответствующий эффективному типу объекта,
- тип, который является типом со знаком или без знака, соответствующий квалифицированной версии эффективного типа объекта,
- агрегированный тип или тип объединения, который включает один вышеупомянутых типов среди его членов (включая, рекурсивно, член субагрегатного или содержащегося объединения), или
- символьный тип.

C++11 3.10 §10.

Если программа пытается получить доступ к сохраненному значению объекта через glvalue, отличного от одного из следующих типов, поведение не определено:
- динамический тип объекта,
- версия динамического типа объекта с квалификацией cv,
- тип, подобный (как определено в 4.4) динамическому типу объекта,
- тип, который является типом со знаком или без знака, соответствующий динамическому типу объекта,
- тип, который является типом со знаком или без знака, соответствующим cv-квалифицированная версия динамического типа объекта
- тип агрегата или объединения, который включает один из вышеупомянутых типов среди его элементов или нестатических элементов данных (включая, рекурсивно, элемент или нестатический член данных субагрегата или содержащий союз),
- тип, который является (возможно, cv-квалифицированным) типом базового класса динамического типа объекта,
- тип char или unsigned char.