Duda con volatile

Iniciado por SARGE553413, 5 Agosto 2014, 19:10 PM

0 Miembros y 2 Visitantes están viendo este tema.

SARGE553413

Hola a todos.
He estado leyendo acerca de para que sirve este keyword (volatile). Lo que he entendido es que sirve para que el compilador no haga ciertas optimizaciones de tipo "ignorar variables que no van a cambiar". Por ej. si tenemos:


bool aux=false;
while(!aux){
  //Hacer cosas sin usar aux.
}


Lo que he entendido es que el compilador detecta que con 'aux' ya no se hace nada más y deja de hacer comparaciones con aux, o bien se da cuenta de que va ha hacer muchas comparaciones y lo mete en un registro de la CPU.

De tal manera que si tenemos el bucle anterior ejecutado por un hilo A  en background y otro hilo B pone 'aux' a cierto, el hilo A no "se entera" porque el compilador ha optimizado código para que deje de hacer comparaciones. (O si lo hace otro proceso, hardware ... )

Esta situación es la que soluciona el modificador "volatile".

Sin embargo lo he probado y ese problema anteriormente mencionado no ocurre, entonces ¿para qué sirve "volatile"?

Esta es la prueba que he hecho:


#include <thread>
#include <mutex>
#include <iostream>

using namespace std;

bool shouldStop;

void pr1();

int main(){
thread th(pr1);
th.detach();
this_thread::sleep_for(chrono::milliseconds(3000));
shouldStop = true;
char *c;
cin >> c;
return 0;
}

void pr1(){
int i = 0;
while (!shouldStop){
cout<<"HOLA "<<i<<endl;
i++;
this_thread::sleep_for(chrono::milliseconds(1000));
}
}


Gracias y saludos.


Eternal Idol

Asegurate de compilar en Release pero vos ahi SI estas modificando el valor de la variable al menos una vez.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

eferion

El modificador volatile, efectivamente, advierte al compilador para que se abstenga de intentar aplicar optimizaciones sobre la variable afectada. Pero ojo... que no tenga el modificador no quiere decir que el compilador tenga forzosamente que aplicar optimizaciones... eso ya depende de varios factores:


  • Tipo de compilador: Cada compilador tiene su propio código y su propio árbol de decisiones.
  • Configuración del compilador: Por muy bueno que sea un compilador... si le dices que no optimice (por ejemplo compilando en modo debug), no aplicará ningún cambio perceptible.
  • Código fuente: Que una variable se pueda optimizar depende del uso que se le de... no solo a la variable, sino también a su entorno. Si tienes más variables que registros, por ejemplo, está claro que el compilador tendrá que decidir quien se queda con los registros en cada momento.

Y toda esta parrafada para al final matizar lo comentado al principio: volatile sirve para asegurarte de que esa variable no va a sufrir optimizaciones... pero esta premisa no dice nada acerca del comportamiento esperado si se elimina el modificador.

SARGE553413

Hola de nuevo, gracias por las respuestas.

Respecto a la primera, no se muy bien qué es compilar en Release. Y sí que cambio la variable 'shouldStop' una vez, pero desde un hilo distinto al que ejecuta el while. Pensaba que esta era una de las situaciones donde entra la utilidad de 'volátile'.

Respecto a la segunda respuesta, utilizo el compilador de visual C++ 2013. Es verdad que no tenía las opciones de optimización activadas, así que he probado a activarlas.
Sigue funcionando bien (y por bien entiendo que el bucle para) sin usar volatile pero, no se por qué, al hacer "cin>>c" me da error el programa, pero ese tema será ya para otro post sobre el compilador de visual c++.

Como conclusión, parece que 'volatile' ha perdido importancia, al igual que 'register'.

Dicho todo esto, mi pregunta es si puede ser buena idea utilizar el modificador 'volatile' si sospechas que cierta variable puede dar problemas alguna vez.

(Y por alguna vez entiendo que otra persona en un futuro pueda modificar tu código, o utilizar otro compilador, o el mismo pero con otros flags de optimización, o versiones nuevas del mismo compilador.)

Gracias y saludos.

ivancea96

Muchos supuestos.

Las variables, si están, son para ser usadas.
Si usas volatile, será porque tienes en mente modificar esas variables o hacerles algo fuera de lo común en C++.

Mi recomendación es, que salvo que pienses hacer algo "extraño", no uses volatile.

Eternal Idol

#5
Cuando vas a usar una variable desde varios hilos tenes que usar sincronizacion (ahi veo que incluis mutex por ejemplo).

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PMY sí que cambio la variable 'shouldStop' una vez, pero desde un hilo distinto al que ejecuta el while. Pensaba que esta era una de las situaciones donde entra la utilidad de 'volátile'.

No, si vos le cambias el valor a la variable no tiene sentido el volatile, justamente es para decirle al compilador que PESE a que PAREZCA que esa variable nunca va a cambiar de valor segun el analisis del codigo que este hace, igual puede cambiar y pedirle que se abstenga de aplicar las optimizaciones correspondientes.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

eferion

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PM
Respecto a la primera, no se muy bien qué es compilar en Release.

Una aplicación que está en desarrollo se compila en modo "debug", es decir con símbolos de depuración y sin optimizaciones para poder depurar el código con facilidad. Cuando la aplicación sale "a la venta", se compila en modo release, es decir, con las optimizaciones oportunas para que la aplicación funcione lo más fluida posible.

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PM
Y sí que cambio la variable 'shouldStop' una vez, pero desde un hilo distinto al que ejecuta el while. Pensaba que esta era una de las situaciones donde entra la utilidad de 'volátile'.

'volatile', como se ha comentado, lo único que hace es impedir que el compilador pueda aplicar optimizaciones sobre la variable. Esta necesidad surge, por ejemplo, a partir de entornos con memoria compartida entre aplicaciones... en los que una variable es accedida a discrección por diferentes fuentes.

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PM
no se por qué, al hacer "cin>>c" me da error el programa, pero ese tema será ya para otro post sobre el compilador de visual c++.

Código (cpp) [Seleccionar]

char* c;
cin >> c;


c es un puntero y no está inicializado.

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PM
Como conclusión, parece que 'volatile' ha perdido importancia, al igual que 'register'.

'volatile' sigue teniendo la misma importancia que tenía en un principio... es una herramienta para casos concretos. Otra cosa es que no te hayas encontrado aún con un caso en el que sea necesario usarla... pero no por eso deja de ser importante... hay proyectos que tendrían bastantes quebraderos de cabeza si no existiese esta palabra clave.

Cita de: SARGE553413 en  6 Agosto 2014, 13:54 PM
Dicho todo esto, mi pregunta es si puede ser buena idea utilizar el modificador 'volatile' si sospechas que cierta variable puede dar problemas alguna vez.

¿problemas? ¿qué clase de problemas? ¿memoria no inicializada tal vez? ¿accesos a memoria no válida? ¿buffer overflow?

'volatile' sirve para lo que sirve. Si no te queda claro cuando has de usarlo es porque no has terminado de entender su finalidad y no te has encontrado con el problema ninguna vez. Lo dicho, deberías usarla cuando tengas, por ejemplo, memoria compartida entre varias aplicaciones.

SARGE553413

Entendido, gracias por las respuestas.