2010-08-12 2 views
11

У меня есть код, который выглядит примерно так, где адрес является 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

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

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

ответ

-2

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

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

+1

Sockets не являются частью реализации компилятора, но часть операционной системы. –

+0

Где у программиста есть «#include », либо что-то файл заголовка.h является частью реализации C или C++, иначе программисту повезло, что все работает так же хорошо, как и они, и программисту приходится решать его самостоятельно. –

+1

Это справедливо только для #include файлов, которые являются частью языка, например. stdlib.h. Файлы Socket include являются частью SDK сокетов, а не компилятором. – EJP

1

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

+1

@R. сначала я не думаю, что утверждается, что 'sa_family/sin_family' является общим исходным элементом. Они должны присутствовать как с одинаковыми значениями. Тогда доступ как OP дал это * является нарушением правил псевдонимов, в основном он выполняет '((struct sockaddr_in *) addr) -> sin_addr', который является распространенной идиомой для совершения подобных действий. –

+0

Кастинг указателя, а затем разыменование его, сам по себе ** никогда ** не нарушает правила сглаживания. Только если вы также разыменовали его, хотя исходный тип правил сглаживания был нарушен. Независимо от того, гарантирует ли POSIX, что '* _family' является общим исходным элементом, на практике это ** является **, а gcc, имеющий определение структуры, знает об этом. Поэтому мое утверждение о нарушении правил псевдонимов было правильным. –

+0

«Они должны присутствовать оба с одинаковыми значениями» ничего не значит. Вы говорите об одной и той же части памяти. Конечно, значения одинаковы. – EJP

2

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

я обычно уйти с этого сначала принимает указатель на struct

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

, а затем с помощью *act.

+1

Если gcc не дает вам то же предупреждение, когда вы используете * act, либо вы не включали те же предупреждения, что и оригинальный плакат, или вы обнаружили ошибку в gcc. –

5

У меня была такая же проблема - это похоже на ошибку в gcc.

я смог обойти его, используя

(*sin).sin_addr 

вместо

sin->sin_addr