2010-09-24 16 views
6

Aquí está el problema: your program temporarily uses some sensitive data and wants to erase it when it's no longer needed. Usar std::fill() en sí mismo no siempre ayudará - el compilador puede decidir que el bloque de memoria no se accede más tarde, por lo que borrarlo es una pérdida de tiempo y eliminar el código de borrado.¿El uso de "puntero a volátil" evita las optimizaciones del compilador en todo momento?

User ybungalobill sugiere using volatile keyword:

{ 
    char buffer[size]; 
    //obtain and use password 
    std::fill_n((volatile char*)buffer, size, 0); 
} 

La intención es que al ver la palabra clave volatile el compilador no tratar de eliminar la llamada a std::fill_n().

Will volatile ¿La palabra clave siempre previene al compilador de tal eliminación de código de modificación de memoria?

+0

Hmmm, creo que no es la situación exacta. Aquí el compilador sabe que la memoria está asignada en la pila, allí no. (por lo que puede apuntar a un registro mapeado en la memoria) – ybungalobill

+0

Estaba a punto de publicar una pregunta similar con respecto a esta respuesta. Es curioso cómo una preocupación puede plantear muchas otras preguntas interesantes;) Aquí está mi +1. – ereOn

+0

Intente declarar el búfer como 'buffer de caracteres volátiles [size];' en lugar de convertirlo en la llamada a 'std :: fill_n'. –

Respuesta

2

El compilador puede optimizar su código porque buffer no es un objeto volátil.

El estándar solo requiere que un compilador se adhiera estrictamente a la semántica para objetos volátiles. Esto es lo que dice C++ 03

Los requisitos mínimos en una aplicación conforme son:

  • En los puntos de secuencia, objetos volátiles son estables en el sentido que las anteriores evaluaciones son completas y evaluaciones posteriores han aún no ocurrió. [...]

y

El comportamiento observable de la máquina abstracta es su secuencia de lecturas y escrituras de datos volátiles y llamadas a la biblioteca de funciones de E/S

En su ejemplo, lo que tienes es leer y escribir usando lvalues ​​volátiles a objetos no volátiles. C++ 0x eliminó el segundo texto que cité arriba, porque es redundante. C++ 0x sólo dice

Los requisitos mínimos en una aplicación conforme son:.

  • acceso a los objetos volátiles son evaluados estrictamente de acuerdo con las reglas de la máquina abstracta [...]

Estos colectivamente se conocen como comportamiento observable del programa.

Si bien se puede argumentar que "los datos volátiles" podría tal vez significar "datos accedidos por lvalues ​​volátiles", que seguiría siendo un buen tramo, la redacción C++ 0x elimina todas las dudas sobre su código y claramente permite implementaciones para optimizarlo lejos.

Pero a medida que la gente me señalaron, es probable que no importa en la práctica. Un compilador que optimice tal cosa probablemente irá en contra de la intención del programador (de lo contrario alguien podría tener un puntero a la volatilidad) y probablemente contenga un error. Aún así, he experimentado vendedores de compiladores que citaron estos párrafos cuando se enfrentaron a informes de errores sobre sus optimizaciones demasiado agresivas. Al final, volatile es específico de la plataforma y se supone que debes verificar el resultado de todas maneras.

+1

_¿Por qué estas reglas tienden a jugar con las palabras? – Pooria

3

Desde el último proyecto de C++ 0x [intro.execution]:

8 Los requisitos mínimos en una aplicación conforme son:

- El acceso a los objetos volátiles se evaluado estrictamente de acuerdo con las reglas de la máquina abstracta.

[...]

12 acceso a un objeto designado por un glvalue volátil (3.10), la modificación de un objeto , llamando a una biblioteca de I/O función, o llamar a una función que hace cualquiera de estas operaciones son todos los efectos secundarios , [...]

Así que incluso el código que ya ha proporcionado no deben ser optimizados.

+2

Al menos, los efectos secundarios de escribir en objetos volátiles no se deben eliminar con la regla de si-si, lo que significa que el código hace lo que debería. El compilador aún puede realizar otras optimizaciones en 'fill_n', como el desenrollado de bucles o las optimizaciones de mirilla del ensamblador. – Doug

1

El contenido de la memoria que desea eliminar puede haberse eliminado ya de la memoria caché interna de la CPU/núcleo a la RAM, donde otras CPU pueden continuar viéndolo. Después de sobreescribirlo, necesita usar una instrucción mutex/barrera de memoria/operación atómica o algo para desencadenar una sincronización con otros núcleos. En la práctica, su compilador probablemente hará esto antes de llamar a cualquier función externa (la publicación de google de Dave Butenhof sobre la dudosa utilidad de volátil en multi-threading), de modo que si lo hace luego, no es un problema importante. En resumen: volátil no es necesario.

Cuestiones relacionadas