2010-01-26 15 views
5

me di cuenta de este comportamiento interesante del compilador g ++, si añado una bandera -O3 al compilador, consigog ++ compilador: indicador de optimización añade un mensaje de advertencia

otsu.cpp:220: warning: ‘x’ may be used uninitialized in this function 

Sin embargo, cuando yo no uso la optimización y en su lugar use un indicador de depuración -g No recibí ninguna advertencia. Ahora, confío más en el compilador cuando el indicador -g está activado; Sin embargo, me pregunto si este es un comportamiento bien definido que debería esperarse.

Para mayor claridad, el código que hace que esto es algo a lo largo de estas líneas:

int x; //uninitialized 


getAValueForX(&x); // function makes use of x, 
        // but x is unitialized 

donde

void getAValueForX(int *x) 
{ 
    *x = 4; 
} 

o algo por el estilo, obviamente más compleja.

+4

publique el código que causa la advertencia –

+0

ok actualizado con un ejemplo concreto. – ldog

+1

Con x es global, cualquier cosa que acceda a x puede hacerlo antes de que se le asigne un valor. O ha simplificado demasiado el ejemplo, o el tipo de análisis requerido para demostrar que no estaría más allá del alcance y la capacidad del optimizador. La advertencia es solo un efecto secundario de la optimización, tiene la oportunidad de advertirle, por lo que lo hace. – Clifford

Respuesta

15

Eso se espera. Las optimizaciones hacen que se ejecute un análisis de código específico y así es como gcc encuentra las variables no inicializadas. Está en la página de manual:

. . . estas advertencias dependen de optimización

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

+1

+1 para el enlace manual; lo explica todo. Probablemente por eso tu respuesta fue mucho más corta que la mía;) – Clifford

1

Mis opciones del compilador:

CFLAGS=-W -Wall\ 
-Wno-non-template-friend\ 
-Wold-style-cast\ 
-Wsign-promo\ 
-Wstrict-null-sentinel\ 
-Woverloaded-virtual 
# -Weffc++ 

-WeffC++ puede ser muy molesto, así que a veces lo intento, pero en general lo guardo apagado. Pruebe estos y otros en el manual y veamos lo que vemos.

3

Esto es realmente muy común con gcc. Y sí, esto es de esperar.

Por lo que entiendo, para optimizar, el compilador genera muchas métricas y transforma el código (o, más precisamente, la representación que tiene del código) de una manera que permite la detección de datos no inicializados o no inicializados. variables no utilizadas para ejemplos (hay algunas otras advertencias como esa, no recuerdo la lista).

Hacer lo mismo sin optimización requeriría hacerlo, y luego descartar todo este análisis. Esto ralentizaría significativamente la compilación sin un buen propósito (especialmente porque, en depuración, no se supone que el compilador reordene el código).

1

Sí, este es un comportamiento bien definido. Cuando el optimizador de GCC no está habilitado, no realiza ciertos tipos de comprobación de ruta de ejecución (para evitar la penalización de rendimiento al realizar este tipo de comprobaciones). Ciertas situaciones, como el uso de variables no inicializadas, solo se pueden detectar cuando se realizan estas comprobaciones adicionales. Por lo tanto, con -O0, GCC no puede advertir acerca de estas condiciones.

1

Bueno, el hecho de que el compilador puede mover cosas para optimizar puede causar problemas y conducir a un comportamiento indefinido (como se indica en el manual se indica a continuación); Creo que sería útil ver el código para intentar y ayudar a que tenga sentido.

Los atajos tomados por código optimizado ocasionalmente pueden producir resultados sorprendentes : algunas variables que declaró puede no existir en absoluto; flujo de control puede moverse brevemente donde no lo hizo esperarlo; algunas sentencias pueden no ser ejecutadas porque calculan los resultados constantes o sus valores ya eran disponibles; algunas sentencias pueden ejecutar en diferentes lugares porque fueron movidas fuera de bucles.

+0

No tiene nada que ver con el cambio de las cosas. Con la optimización desactivada, el compilador ni siquiera realiza el análisis que podría detectar variables no inicializadas. La optimización nunca * causará * que una variable no se inicialice. –

3

El análisis de flujo de código que realiza el optimizador le permite detectar problemas potenciales que la compilación normal (y más rápida) no puede detectar. El problema siempre estuvo ahí, el compilador simplemente no lo verificó.

Incluso cuando se emite esta advertencia, de hecho puede no ser un problema debido al uso real de la función en la práctica; el compilador asumirá que todos los valores posibles de los tipos de sus argumentos (y cualquier variable externa utilizada dentro de la función) pueden ocurrir en todas las combinaciones posibles, lo que lleva a al menos una ruta donde la variable se usa sin que se le asigne un valor. Su uso real tendrá un conjunto mucho más restrictivo de estados posibles, por lo que la ruta nunca puede ocurrir en la práctica. La solución simple es simplemente inicializar la variable solo para cerrar el compilador, no le costará nada.

Siempre utilizo el optimizador como una forma de análisis estático de un hombre pobre incluso cuando finalmente no tengo la intención de utilizarlo en el código de producción. Igualmente, a menudo uso más de un compilador por la misma razón. Algunos compiladores realizan comprobaciones que otros no hacen, o generan mensajes redactados de forma diferente para los mismos errores, lo que a menudo ayuda a interpretar algunos de los mensajes más obtusos.

Cita:

Confío en que el compilador más cuando la bandera -g está en

Si bien es cierto que si un compilador tiene un error que es probable que sea en el optimizador (siendo la parte más compleja), para un compilador maduro como GCC, este sería un hallazgo muy raro. Por el contrario, las personas a menudo descubren que su código de trabajo falla cuando se optimiza; la mayoría de las veces el código siempre tenía fallas (quizás se basaba en un comportamiento definido o no definido por el compilador), y el optimizador acaba de exponer ese defecto. Así que sugiero que, si encuentra que su código se está rompiendo en optimización, sospeche el código antes del compilador: se aplica el Razor de Occam.

+0

+1 Encuentro que probar una variedad de compiladores puede ofrecer una perspectiva interesante de su código y llamar la atención sobre las suposiciones implícitas que haya realizado que podrían no tener lugar en otro lugar. Esto a menudo se descuida. – asveikau

0

Tengo el mismo problema en mi compilador msvc 6. Inicializando la variable en cuestión, elimina la posibilidad de una ruta incorrecta desde el punto de vista del compilador.

Cuestiones relacionadas