3

在这个程序中,我编写了几个公式,但对于一个公式,我得到的结果不一致,尽管每次运行的代码和输入都相同。有问题的函数是“WqFormula”。在某些运行中,我得到正确的结果,即 0.041667,而在其他运行中,我得到 0.000000。我正在使用 GCC 4.6.3 在 Ubuntu(64 位)上编译。另一件事是我尝试使用 GCC 4.4.6 在 PC 上编译和运行它,它为每个公式提供了完全不同的结果。继承人的代码:

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;
}

每次应该打印的是这样的:

PoFormula 是 0.500000

L公式为 0.750000

W公式为 0.375000

Lq公式为 0.083333

WqFormula 是 0.041667

如果需要,我很乐意提供更多信息。

4

1 回答 1

3

以下函数summation在未初始化的情况下使用:

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

所以你不能指望这个函数的任何结果都是有意义的。

你的编译器可以警告你这样的问题,如果你要求它(你真的应该!):

对于 GCC,使用-Wall -Wextra(我个人也使用-pedantic, YMMV)编译以获得尽可能多的警告。但是,在这种特殊情况下,GCC 似乎对问题视而不见,直到您使用-O.

您现在可以停止阅读,只需-Wall -Wextra -O在编译时使用即可捕获此问题。


GCC 的未初始化变量分析有两种不同的检查——“肯定使用未初始化”和“可能使用未初始化”。根据是否启用优化,分析的工作方式会有所不同:

  • 如果优化关闭(-O0默认),编译器会在一个分析过程中执行两个检查。
  • 如果优化是开启的,编译器会执行两遍——第一遍只执行“绝对未初始化”检查,第二遍在优化之后发生(因为优化可能会改变控制流)并执行两个检查。

我对 GCC 内部结构不够熟悉,无法了解在您的代码中隐藏这个问题会发生什么,但如果有人想更深入地挖掘,我将其简化为这个测试用例。如果展开循环,即使没有-O,也会收到警告,因此循环展开优化可能与它有关。


如果您使用 MSVC,请编译/W4以获取最多的警告。MSVC 将此未初始化的变量报告为默认警告级别的问题,无论是否进行优化。

于 2012-09-23T08:06:27.427 回答