Указатель разыменования нарушает строгие правила сглаживания с использованием сокетов Беркли
У меня есть код, который выглядит примерно так, где addr это sockaddr*:
struct sockaddr_in *sin = (struct sockaddr_in *) addr;
const char *IP=inet_ntoa(sin -> sin_addr);
Я считаю, что это очень типичный код для использования сокетов Беркли.
Однако, когда я компилирую это, я получаю следующее предупреждение:dereferencing pointer 'sin' does break strict anti-aliasing rules
Ища в Интернете, я нахожу некоторое обсуждение факта, что способ, которым я делаю вещи, довольно типичен, но это предупреждение компилятора также довольно реально и не очень хорошо.
Как правильно переделать этот код, чтобы исправить предупреждение, а не просто заставить его замолчать?
4 ответа
У меня была такая же проблема - похоже, ошибка в gcc.
Я смог обойти это с помощью
(*sin).sin_addr
вместо
sin->sin_addr
Да, это известная проблема с gcc и сокетами. Проблема в основном заключается в том, что способ, которым спроектирован этот ip[46] материал, несовместим с предположениями, которые люди gcc думают, что они могут сделать вывод о псевдонимах указателей.
Я обычно схожу с рук, сначала беря указатель на struct
struct in_addr* act = &(sin->sin_addr);
а затем с помощью *act
,
В зависимости от того, как вы использовали struct sockaddr
Я думаю, что либо ваш код не работает, либо GCC не работает. struct sockaddr
а также struct sockaddr_in
иметь общий начальный элемент (sa_family
/sin_family
) поэтому он не нарушает правила псевдонимов, если вы обращались только к этому элементу через оба указателя; это разрешено C99. Более того, struct sockaddr
не имеет других элементов, к которым вам разрешен доступ. Это в значительной степени непрозрачный тип для примитивного полиморфизма адреса сокета. Если вы ковырялись в специфических для реализации внутренностях в struct sockaddr
или еще хуже, если вы объявили struct sockaddr
объект, а не просто указатель или выполненное копирование между такими объектами, ваш код не работает. Если вы этого не сделали, а gcc выдает предупреждение о том, что вы нарушили правила псевдонимов, то генерация предупреждений gcc не работает. Я конечно не удивлюсь, если это последнее.
Если ваш заголовочный файл и ваш компилятор являются частями одной и той же реализации на C или C++, пожалуйтесь вашему поставщику и попросите его добавить подходящую #pragma в свой заголовочный файл, чтобы заставить их компилятор замолчать. Как разработчик, им разрешено играть в такие игры, если они обеспечивают соответствующую реализацию.
Если ваш заголовочный файл и ваш компилятор пришли из двух отдельных реализаций C или C++, вам повезло, что все работает так же хорошо, как и они, и вы должны решить это самостоятельно.