“El puntero con punteo de tipo desreferenciará las reglas de aliasing estricto”

Utilizo un código donde lanzo un enum * a int *. Algo como esto:

enum foo { ... } ... foo foobar; int *pi = reinterpret_cast(&foobar); 

Al comstackr el código (g ++ 4.1.2), aparece el siguiente mensaje de advertencia:

 dereferencing type-punned pointer will break strict-aliasing rules 

Busqué en Google este mensaje y descubrí que ocurre solo cuando está activada la optimización de aliasing estricta. Tengo las siguientes preguntas:

  • Si dejo el código con esta advertencia, ¿generará un código potencialmente incorrecto?
  • ¿Hay alguna forma de evitar este problema?
  • Si no lo hay, ¿es posible desactivar el alias estricto desde dentro del archivo fuente (porque no quiero desactivarlo para todos los archivos fuente y no quiero crear una regla Makefile separada para este archivo fuente). )?

Y sí, realmente necesito este tipo de aliasing.

En orden:

  • Sí. GCC asumirá que los punteros no pueden alias. Por ejemplo, si asigna a través de uno y luego lee desde el otro, GCC puede, como optimización, reordenar la lectura y la escritura: he visto que esto sucede en el código de producción, y no es agradable depurarlo.

  • Varios. Puede usar una unión para representar la memoria que necesita para reinterpretar. Podría usar un reinterpret_cast . Puede transmitir a través de char * en el punto donde reinterpreta la memoria – char * se define como capaz de alias cualquier cosa. Puede usar un tipo que tenga __attribute__((__may_alias__)) . Puede desactivar las suposiciones de alias globalmente utilizando -fno-strict-aliasing.

  • __attribute__((__may_alias__)) en los tipos utilizados es probablemente lo más cercano que se puede llegar a deshabilitar la suposición para una sección particular de código.

Para su ejemplo particular, tenga en cuenta que el tamaño de una enumeración está mal definido; GCC generalmente usa el tamaño entero más pequeño que se puede usar para representarlo, por lo que la reinterpretación de un puntero a una enumeración como un entero podría dejarte con bytes de datos no inicializados en el entero resultante. No hagas eso. ¿Por qué no simplemente lanzar a un tipo de entero adecuado?

¿Pero por qué estás haciendo esto? Se romperá si sizeof (foo)! = Sizeof (int). El hecho de que una enumeración sea como un número entero no significa que esté almacenada como una sola.

Entonces sí, podría generar código “potencialmente” incorrecto.

Puede usar el siguiente código para transmitir sus datos:

 template struct alias_cast_t { union { F raw; T data; }; }; template T alias_cast(F raw_data) { alias_cast_t ac; ac.raw = raw_data; return ac.data; } 

Ejemplo de uso:

 unsigned int data = alias_cast(raw_ptr); 

¿Has mirado esta respuesta ?

La regla de aliasing estricta hace que esta configuración sea ilegal, dos tipos no relacionados no pueden apuntar a la misma memoria. Solo char * tiene este privilegio . Desafortunadamente todavía puedes codificar de esta manera, tal vez recibir algunas advertencias, pero que compile bien.

El alias estricto es una opción del comstackdor, por lo que debe desactivarlo desde el archivo MAKE.

Y sí, puede generar código incorrecto. El comstackdor asumirá efectivamente que foobar y pi no están unidos, y supondrá que *pi no cambiará si foobar cambió.

Como ya se mencionó, use static_cast en static_cast lugar (y sin punteros).