Описание тега strict-aliasing
Строгий псевдоним - это сделанное компилятором 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.