2014-09-09 5 views
1

У меня есть большая программа, которая имеет большое количество фрагментов формыкомпилятор предупреждения о типе каламбуров в НКУ

float t = amplitudes->read(current_element); 
    if (*((uint32_t *) &t) == 0xsomereservedvalue) 
     do_something 
    else 
      do_something_else 

Это нормально компилируется с GCC 3.4.x нет предупреждений. Скомпилировано с -Wtrict-aliasing = 2 все еще никаких предупреждений. Недавно я попробовал компиляцию с gcc4.4 и получил огромное количество предупреждений о пустых ссылках типа. Может ли кто-нибудь сказать мне, есть ли разумная ситуация, при которой такой код может потерпеть неудачу? Насколько я вижу, тип punning - это только потенциальная проблема, если оптимизация упорядочивает такие вещи, что что-то может быть записано из реестра после того, как другая строка кода читает его, что, поскольку мы возвращаемся к функции здесь, просто может Слушай. Я что-то упустил здесь, или gcc, будучи немного braindead?

+0

Какое точное предупреждение? – doron

+0

предупреждение: разыменованный тип-указатель нарушит правила строгого сглаживания – camelccc

ответ

1

Конечно, предупреждает. Я только что проверил gcc 4.8.2, он тоже предупреждает. Представьте себе, что размер поплавка для целевой машины составляет 16 бит, и вы пытаетесь читать 32 бита после границ данных. Это UB.

btw Я не согласен с использованием reinterpret_cast в этом случае. Единственный полезный способ для reinterpret_cast - *(reinterpret_cast<char *>(&t)), даже *(reinterpret_cast<unsigned *>(&t)) все равно нарушит правила псевдонимов, и вы получите то же предупреждение. Это потому, что компилятор знает только на C++, что char является наименьшим, поэтому каждый тип может быть применен к нему.

У GCC есть атрибут, указывающий, что данный тип может быть псевдонимом. Его также не так просто использовать.

unsigned * __attribute__ ((__may_alias__)) pu = (unsigned *) &t; 
if (*pu == 0xsomereservedvalue) 
    do_something(); 
else 
    do_something_else(); 

Но здесь вещи, по крайней мере, имеют смысл. Мы запрашиваем указатель на алиасы. Стоимость: код сейчас не переносится.

Так что после всех соображений я рекомендую только поставить опцию -fno-strict-aliasing, если вы действительно уверены, что знаете, что делаете.

+0

Итак, вы рекомендуете отключить предупреждение компилятора глобально вместо «reinterpret_cast» или рефакторинга кода (например, использование «союза») в интересующей точке? Не уверен, что я могу согласиться с этим ... – DevSolar

+0

Может быть, рефакторинг кода - хорошая идея. Использование reinterpret_cast здесь не помогло бы вообще. Попытайтесь написать что-нибудь с этим. –

+0

Интересно, что опция -fno-strict-aliasing генерирует исполняемый файл, который немного меньше, даже для gcc3.4. Это влияет на двоичный файл. – camelccc

1

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

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

Для гарантии правильности необходимо использовать либо memcpy, когда тип punning или build со строгим псевдонимом отключен. (Союзы немного неясны)

Взгляните here на другое более подробное сообщение о строгом псевдониме.

Смежные вопросы