¿Resultados inconsistentes (C)?

En este progtwig, he codificado en varias fórmulas y para una fórmula estoy obteniendo resultados inconsistentes, aunque es el mismo código y entradas para cada ejecución. La función en cuestión es “WqFormula”. En algunas ejecuciones obtengo el resultado correcto, que es 0.041667 y en otras ejecuciones, obtengo 0.000000. Estoy comstackndo en Ubuntu (64-bit) usando GCC 4.6.3. Otra cosa es que intenté comstackr y ejecutar esto en una PC usando GCC 4.4.6 y me dio resultados completamente diferentes para cada fórmula. Aquí está el código:

float PoFormula(float, float, int); float LFormula(float, float, int); float WFormula(float, float, int); float LqFormula(float, float, int); float WqFormula(float, float, int); int main() { int n, m; //# of arrivals, # of service channels float mu, lambda; //avg serviced, arrivals in time period printf("lambda (l) = "); scanf ("%f", &lambda); printf("mu (m) = "); scanf ("%f", &mu); printf("m (M) = "); scanf("%i", &m); float test, test2, test3, test4, test5; test = PoFormula(lambda, mu, m); printf("PoFormula is %f\n", test); test2 = LFormula(lambda, mu, m); printf("LFormula is %f\n", test2); test3 = WFormula(lambda, mu, m); printf("WFormula is %f\n", test3); test4 = LqFormula(lambda, mu, m); printf("LqFormula is %f\n", test4); test5 = WqFormula(lambda, mu, m); printf("WqFormula is %f\n", test5); return; } float PoFormula(float lambda, float mu, int m) { float summation, factorial = 1; int i, j; for (i=0; i < (m); i++) { for (j=1; j < (i+1); j++) factorial *= j; factorial = 1 / factorial; factorial = factorial * pow ((lambda/mu), i); summation += factorial; } factorial = 1; for (j=1; j < (m+1); j++) factorial *= j; factorial = 1 / factorial; factorial = factorial * pow ((lambda/mu), m); factorial = factorial * ((m*mu)/((m*mu) - lambda)); factorial += summation; factorial = 1 / factorial; return factorial; } float LFormula(float lambda, float mu, int m) { float factorial = 1, po; int j; po = PoFormula(lambda, mu, m); for (j=1; j < (m); j++) factorial *= j; factorial *= pow(((m*mu) - lambda), 2); factorial = (((lambda*mu)*(pow((lambda/mu),m)))/factorial) * po; factorial += (lambda/mu); return factorial; } float WFormula(float lambda, float mu, int m) { float factorial = LFormula(lambda, mu, m); factorial /= lambda; return factorial; } float LqFormula(float lambda, float mu, int m) { float factorial = LFormula(lambda, mu, m); factorial -= (lambda/mu); return factorial; } float WqFormula(float lambda, float mu, int m) { float factorial = LqFormula(lambda, mu, m); factorial /= lambda; return factorial; } 

Lo que debería estar imprimiendo cada vez es esto:

PoFormula es 0.500000

LFormula es 0.750000

WFormula es 0.375000

LqFormula es 0.083333

WqFormula es 0.041667

Estaré encantado de proporcionar más información si es necesario.

La siguiente función utiliza la summation sin inicializarla:

 float PoFormula(float lambda, float mu, int m) { float summation, factorial = 1; for (i=0; i < (m); i++) { // .... summation += factorial; } 

Por lo tanto, no puede esperar que los resultados de esta función sean significativos.

Tu comstackdor puede advertirte sobre problemas como este, si lo pides (¡y realmente deberías!):

Para GCC, compile con -Wall -Wextra (personalmente, también uso -pedantic , YMMV) para obtener todas las advertencias posibles. Sin embargo, en este caso particular, GCC parece estar ciego al problema hasta que se habilita la optimización con -O .

Puede dejar de leer ahora y simplemente usar -Wall -Wextra -O al comstackr para detectar este problema.


El análisis de la variable no inicializada de GCC tiene dos controles diferentes: " definitivamente se usa sin inicializar" y " posiblemente se usa sin inicializar". El análisis funciona de manera diferente dependiendo de si la optimización está habilitada:

  • Si la optimización está desactivada ( -O0 , predeterminado), el comstackdor realiza ambas comprobaciones en una sola pasada de análisis.
  • Si la optimización está activada, el comstackdor realiza dos pasadas en su lugar: la primera pasada solo realiza la verificación "definitivamente sin inicializar", la segunda ocurre después de la optimización (porque la optimización podría cambiar el flujo de control) y realiza ambas comprobaciones.

No tengo suficiente familiaridad con las partes internas de GCC para ver qué sucede para ocultar este problema en su código, pero lo reduje a este caso de prueba , si alguien quiere profundizar más. Si desenrolla el bucle, recibirá la advertencia incluso sin -O , por lo que las optimizaciones del desenrollado del bucle podrían tener algo que ver con eso.


Si usa MSVC, compile con /W4 para obtener la mayor cantidad de advertencias. MSVC informa que esta variable no inicializada es un problema en el nivel de advertencia predeterminado, con y sin optimización.