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

У меня есть код, который выглядит примерно так, где addr - sockaddr *:

struct sockaddr_in *sin = (struct sockaddr_in *) addr;
const char *IP=inet_ntoa(sin -> sin_addr);

Я считаю, что это очень типичный код для использования сокетов Berkeley.

Однако, когда я скомпилирую это, я получаю следующее предупреждение:
dereferencing pointer 'sin' does break strict anti-aliasing rules

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

Какой правильный способ повторить этот код, чтобы исправить это предупреждение, а не просто отключить его?

Ответ 1

У меня была такая же проблема - она ​​выглядит как ошибка в gcc.

Мне удалось обойти это, используя

(*sin).sin_addr

вместо

sin->sin_addr

Ответ 2

Да, это проблема с gcc и сокетами. Проблема в основном состоит в том, что способ создания этого файла ip [46] несовместим с предположениями, которые gcc-люди считают, что они могут вывести о сглаживании указателей.

Я обычно избегаю этого, сначала сделав указатель на struct

struct in_addr* act = &(sin->sin_addr);

а затем используя *act.

Ответ 3

В зависимости от того, как вы использовали struct sockaddr, я думаю, что либо ваш код сломан, либо gcc не работает. struct sockaddr и struct sockaddr_in имеют общий начальный элемент (sa_family/sin_family), поэтому он не нарушает правила сглаживания, если вы получили доступ только к этому элементу через оба указателя; это разрешено C99. Более того, struct sockaddr не имеет других элементов, к которым вам разрешен доступ. В основном это непрозрачный тип для примитивного полиморфизма адресов сокетов. Если вы столкнулись со специфичными для реализации внутренностями в struct sockaddr или, что еще хуже, если вы объявили объект struct sockaddr, а не просто указатель или выполнили копирование между такими объектами, ваш код будет нарушен. Если вы этого не сделали, и gcc предупреждает, что вы нарушили правила псевдонимов, то генерируется предупреждение gcc. Я, конечно, не удивлюсь, если это последнее.

Ответ 4

Если ваш заголовочный файл и ваш компилятор являются частью одной и той же реализации на C или С++, обратитесь к своему поставщику и попросите их поместить подходящую #pragma в свой заголовочный файл, чтобы отключить их компилятор. Как разработчик, им разрешено играть в подобные игры, если они обеспечивают соответствующую реализацию.

Если ваш заголовочный файл и ваш компилятор произошли от двух отдельных реализаций C или С++, вам повезло, что все работает так же хорошо, как и они, и вы должны решить его самостоятельно.