2012-04-12 13 views
12

Si llamo a una función que tiene un parámetro volátil, y ese parámetro no se utiliza, ¿debe el compilador, no obstante, producir el parámetro?¿Se debe respetar un parámetro volátil no utilizado?

void consume(volatile int) { } 

... 

consume(some_expr); 

GCC hace honor a esto, pero no estoy seguro si la redacción de volátil en los estándares lo requiere. En mi opinión GCC está haciendo lo correcto - esto es lógicamente una asignación a una variable volátil y por lo tanto no debe ser omitido (según 1,9-8 del C++ estándar)

NOTA: El propósito de esto es para evitar que el optimizador elimine la evaluación del código. Es decir, fuerza some_expr para ser evaluado. Permite que la expresión se optimice, pero asegura que realmente se realice.

He añadido C y C++ como etiquetas, ya que la respuesta a ambas me interesa si hubiera alguna diferencia. No creo que haya sin embargo.

RESPUESTA: Escogí la primera porque creo que es la realización práctica correcta de la norma. Sin embargo, el punto de vista filosófico de Steve es muy interesante y, de hecho, puede significar que el estándar es ambiguo.

Respuesta

5

El argumento sin nombre de consume no se puede leer, ya que no tiene nombre. Sin embargo, se inicializa y esa inicialización (con some_expr) es un efecto secundario visible. Por lo tanto, el compilador puede no optimizar la inicialización.

Si esto requiere la evaluación real de some_expr es otra cuestión. En general, no es un efecto secundario visible, pero podría ser si some_expr contiene volatile subexpresiones.

[editar] Tenga en cuenta que la parte "sin nombre" puede ocurrir en dos lugares. La persona que llama en general no tiene manera de saber si un parámetro se llama (y mucho menos si se usa) P. ej.

void consume(volatile int x); 
consume(some_expr); 
// other .cpp 
void consume(volatile int) { } // Same function. 
+0

Sí, entiendo 'some_expr', esa es mi intención. El compilador aún puede optimizar eso como quiera, pero el _valor real_ de ese cálculo (según lo dictado por la máquina abstracta) debe obtenerse de alguna manera para asignarlo a la variable. –

+0

Es cierto, pero eso podría estar disponible a través de Eliminación de Subexpresión Común, por ejemplo. Mi punto es que si el compilador sabe mágicamente 'some_expr == 5', la inicialización del argumento sin nombre con 5 sigue siendo observable. – MSalters

+0

Sí, creo que estamos de acuerdo en eso. Lo admito, suena realmente extraño ya que el uso no es inmediatamente evidente, pero me ayuda mucho en las pruebas de rendimiento. –

1

Es posible argumentar lo contrario, pero creo que una aplicación puede omitir accede a volatile objetos automáticos, siempre que de otro modo no hacen ninguna diferencia con el programa y siempre también que sea prohíbe el programador de la observación de la pila (a través de páginas no asignadas o de solo lectura, depuradores, etc.), o al menos advierte que hacerlo no siempre tendrá el efecto esperado. Un parámetro sin nombre se ajusta a esa descripción.

La razón es que la regla "como si" habla sobre los efectos secundarios visibles, y dice que los accesos volátiles son efectos secundarios visibles. Pero si el programa en sí mismo no depende de ninguna manera de ellos, entonces el estándar no dice que el objeto debe ubicarse "en la pila". El estándar le permite estar en una ubicación de memoria especial provista por el hardware, que no puede leerse de ninguna manera, solo se escribe en ella, y escribir en ella no tiene ningún efecto físico en el hardware. Como eso está permitido, parece absurdo decir que es "requerido por el estándar" que esta escritura sin efecto en realidad sigue adelante. ¿Cómo lo sabría alguien? La norma no exige que haya instrucciones en el binario para realizar la escritura, sino que exige que el objeto secreto mágico e ilegible deba asumir un valor particular. Si afirmo que tiene ese valor, no puede probar que estoy equivocado :-)

No es posible escribir un programa conforme que dependa de que se produzca realmente un acceso tan volátil, o para detectar si some_expr fue o no evaluado.Realmente es entre usted y su depurador si fue computado o no. He visto que los depuradores salen mal por menos.

Por lo tanto, creo que es una implementación permitió romper su propio depurador, al igual que es permitido no proporcionar un depurador funciona en absoluto. No veo de inmediato por qué querría. En la práctica, esperaría que marcar el parámetro volátil tenga aproximadamente el mismo efecto que mover la definición de la función a alguna parte que el optimizador no pueda encontrar; actuará para garantizar que se pueda usar el valor.

+0

La asignación, como sea que se haga, es un efecto secundario observable para el procesador, en realidad tiene que hacer algo. No tiene que ser una variable real, y podría ser un registro o una ubicación especial, pero mi comprensión/esperanza es que la tarea realmente tiene que hacerse, incluso si nada podría leerla. Entonces, la pregunta podría reformularse como "¿prevalece lo volátil sobre la regla de si ...?" –

+0

Al observar el estándar, un elemento volátil es, por definición, un comportamiento observable (último párrafo en 1.9-8). Entonces, incluso si el compilador puede determinar que el valor no se puede usar, aún así debe asignar el valor en alguna parte. –

+0

La pregunta sobre cómo observar algo está relacionada con la pregunta de si se puede observar, pero ciertamente no es la misma pregunta. Tal vez este hilo debe continuarse en Philosophy.SE;) – MSalters

Cuestiones relacionadas