Указатель разыменования нарушает строгие правила сглаживания с использованием сокетов Беркли

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

Другие вопросы по тегам