1

我用 PVS Studio 分析器扫描了我的代码,我对为什么会出现这个错误以及如何解决这个问题感到困惑。

V550 一个奇怪的精确比较:* dest == value。使用具有定义精度的比较可能会更好:fabs(A - B) < Epsilon。

bool PipelineCache::SetShadowRegister(float* dest, uint32_t register_name) {
    float value = register_file_->values[register_name].f32;
    if (*dest == value) {
        return false;
    }
    *dest = value;
    return true;
}

我猜想像这样更改代码:

bool PipelineCache::SetShadowRegister(float* dest, float* epsilon uint32_t register_name) {
    float value = register_file_->values[register_name].f32;
    return fabs(dest - value) < epsilon;
}
4

1 回答 1

1

谁想知道,我们正在谈论这段代码。

我将尝试解释 PVS 工作室开发人员试图通过此消息实现的目标。引用他们关于 V550的参考资料:

考虑这个样本:

double a = 0.5;
if (a == 0.5) //OK
    x++;

double b = sin(M_PI / 6.0);
if (b == 0.5) //ERROR
    x++;

第一个比较 'a == 0.5' 为真。第二个比较 'b == 0.5' 可能同时为真和假。'b == 0.5' 表达式的结果取决于所使用的处理器、编译器的版本和设置。例如,当我们使用 Visual C++ 2010 编译器时,“b”变量的值为 0.49999999999999994。

他们想说的是,比较浮点数很棘手。如果您只是分配浮点数,请将其存储并在内存中移动,以便稍后在此函数中与自身进行比较 - 随意忽略此错误消息。

如果您希望执行一些位表示检查(我真的认为您正在这样做),请参见下文

如果您正在对浮点数执行一些大规模计算,并且您是一名游戏开发人员,正在计算敌方战列巡洋舰的坐标 - 这个警告是您最好的朋友之一。


无论如何,让我们回到你的情况。正如 PVS-Studio 通常发生的那样,他们没有看到确切的错误,但他们为您指出了正确的方向。您实际上比较两个浮点值,但您做错了。问题是,如果您要比较的两个浮点数都包含 NaN(即使在相同的位表示中),您将得到*dest != value,并且您的代码将无法按您想要的方式工作。

在这种情况下,您最好将内存重新解释float *uint32_t(或任何与您的目标具有相同大小的整数类型float)并改为比较它们。

例如,在您的特定情况下,register_file_->values[register_name]type xe::gpu::RegisterFile::RegisterValue,它已经支持uint32_t表示。

作为副作用,这将消除警告:)

于 2017-07-09T22:07:16.803 回答