Strict Pointer Aliasing: ¿El acceso a través de un puntero/referencia 'volátil' es una solución?

StackOverflow https://stackoverflow.com/questions/2981827

Pregunta

En los talones de un problema específico, una respuesta y comenta a su cuenta, me gustaría entender si es una solución adecuada, solución/hack o simplemente incorrecta.

Específicamente, reescribí código:

T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
  ...

Como:

T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
  ...

con un volatile Calificador para el puntero.

Supongamos que tratar T como int en mi situación tiene sentido. ¿Acceda esto a través de un volatile ¿Resolver un problema de alias de puntero?

Para una referencia, de la especificación:

Nota: Volátil es una pista de la implementación para evitar la optimización agresiva que involucra el objeto porque el valor del objeto podría cambiarse por medios indetectables por una implementación. Ver 1.9 para una semántica detallada. En general, la semántica del volátil está destinada a ser la misma en C ++ que en C. - Nota final

EDITAR:

El código anterior resolvió mi problema al menos en GCC 4.5.

¿Fue útil?

Solución

Volátil no puede ayudarlo a evitar el comportamiento indefinido aquí. Entonces, si funciona para usted con GCC, es suerte.

Supongamos que T es una cápsula. Entonces, la forma correcta de hacer esto es

T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
  …

¡Ahí! No hay problema de alias estricto y ningún problema de alineación de memoria. GCC incluso maneja MEMCPY como una función intrínseca (no se inserta ninguna llamada de función en este caso).

Otros consejos

Volátil no puede ayudarlo a evitar el comportamiento indefinido aquí.

Bueno, cualquier cosa con respecto volatile no es claro en el estándar. Principalmente estuve de acuerdo con su respuesta, pero ahora me gustaría estar un poco en desacuerdo.

Para entender que volatile significa que el estándar no está claro para la mayoría de las personas, especialmente algunos escritores de compiladores. Es mejor pensar:cuando usas volatile (y solo cuando), C/C ++ es un ensamblaje de alto nivel.

Al escribir a un volatile lvalue, el compilador emitirá una tienda o una tienda múltiple si uno no es suficiente (volatile no implica atómico).

Al escribir a un volatile Lvalue, el compilador emitirá una carga o una carga múltiple si uno no es suficiente.

Por supuesto, donde no hay una carga o tienda explícita, el compilador solo emitirá instrucciones que implican una carga o tienda.

Sellibitze dio la mejor solución: usar memcpy Para reinterpretaciones de bits.

Pero si todos los accesos a una región de memoria se realizan con volatile Lvalues, Está perfectamente claro que las estrictas reglas de alias no se aplican. Esta es la respuesta a su pregunta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top