2010-08-12 5 views
11

que tengo código que se ve algo como esto, donde addr es un sockaddr *:puntero eliminación de referencias hace romper estrictas normas anti-aliasing usando sockets Berkeley

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

Creo que esto es un código muy típica para el uso de Berkeley enchufes

Sin embargo, cuando compilo esto, yo estoy haciendo la siguiente advertencia:
dereferencing pointer 'sin' does break strict anti-aliasing rules

La búsqueda en línea, encuentro alguna discusión sobre el hecho de que la forma en que estoy haciendo las cosas es bastante típico, pero esto la advertencia del compilador también es bastante real y no es algo bueno.

¿Cuál es la forma correcta de volver a hacer este código para corregir la advertencia, y no solo silenciarlo?

Respuesta

-2

Si su archivo de cabecera y su compilador son partes de la misma implementación de C o C++, póngase en contacto con su proveedor y pídales que pongan un #pragma adecuado en su archivo de cabecera para silenciar su compilador. Como implementadores, pueden jugar así, siempre que proporcionen una implementación conforme.

Si su archivo de cabecera y su compilador provienen de dos implementaciones separadas de C o C++, tiene suerte de que las cosas funcionen tan bien como lo hacen, y debe resolverlo usted mismo.

+1

sockets no son parte de una implementación del compilador sino que forma parte del sistema operativo. –

+0

Donde el programador tiene "#include ", ya sea ese archivo de encabezado algo.h es parte de una implementación C o C++, o bien el programador tiene suerte de que las cosas funcionen tan bien como lo hacen y el programador tiene que resolverlas por sí mismo. –

+1

Eso solo es cierto para #incluir archivos que son parte del idioma, p. stdlib.h. Los archivos de inclusión de socket forman parte de un SDK de sockets, no del compilador. – EJP

1

Dependiendo de cómo haya usado struct sockaddr, creo que su código está roto o gcc está roto. struct sockaddr y struct sockaddr_in tienen un elemento inicial común (sa_family/sin_family) por lo que no infringe las reglas de alias si ha accedido solo a este elemento a través de ambos punteros; hacerlo así está permitido por C99. Además, struct sockaddr no tiene otros elementos a los que tenga acceso. Es en gran medida un tipo opaco para el polimorfismo de la dirección del zócalo primitivo. Si ha estado hurgando en elementos internos específicos de la implementación en struct sockaddr, o peor aún, si declaró un objeto struct sockaddr en lugar de solo un puntero o realizó una copia entre dichos objetos, su código se rompe. Si no lo hiciste, y gcc está dando una advertencia diciendo que has roto las reglas de aliasing, entonces la generación de advertencia de gcc está rota. Seguramente no me sorprendería si fuera el último.

+1

@R. primero, no creo que se afirme que 'sa_family/sin_family' sea un elemento inicial común. Deben estar presentes ambos, con valores idénticos. Entonces el acceso como el OP lo dio * es * una violación de las reglas de aliasing, básicamente él está haciendo '((struct sockaddr_in *) addr) -> sin_addr' que es un idioma común para hacer tales cosas. –

+0

Lanzar un puntero y luego desreferenciarlo es, en sí mismo, ** nunca ** una violación de las reglas de aliasing. Solo si también lo desreferenció aunque el tipo original se puede violar las reglas de aliasing. Independientemente de si POSIX garantiza que '* _family' es un elemento inicial común, en la práctica ** es **, y gcc, que tiene la definición de estructura, lo sabe. Por lo tanto, mi afirmación de que no se han infringido las reglas de aliasing es correcta. –

+0

'Deben estar presentes ambos, con valores idénticos' no significa nada. Estás hablando de la misma pieza de memoria. Por supuesto, los valores son los mismos. – EJP

2

Sí, este es un problema conocido con gcc y sockets. El problema básicamente parece ser que la forma en que se diseñan estas cosas ip [46] es incompatible con las suposiciones que las personas gcc creen que pueden deducir sobre aliasing de punteros.

por lo general se salen con esto tomando primero un puntero en la struct

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

y luego usando *act.

+1

Si gcc no le da la misma advertencia cuando usa * act, o no activó las mismas advertencias que el original, o encontró un error en gcc. –

5

Tuve el mismo problema: parece un error en gcc.

que era capaz de conseguir alrededor de él mediante el uso de

(*sin).sin_addr 

en lugar de

sin->sin_addr 
Cuestiones relacionadas