PVS-Studio抱怨浮动比较

时间:2017-07-09 18:05:39

标签: c++ pvs-studio

我使用PVS Studio分析器扫描了我的代码,我对此错误以及如何解决此问题感到困惑。

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

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

1 个答案:

答案 0 :(得分:1)

无论谁想,我们都在谈论this代码。

我将尝试解释PVS工作室开发人员试图通过此消息实现的目标。引用他们的reference关于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代表。

作为副作用,这将引出警告:)