Я отсканировал свой код с помощью анализатора 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;
}
Кто бы ни задавался вопросом, мы говорим о этот код.
Я попытаюсь объяснить, чего разработчики студии 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’ зависит от процессора, версии компилятора и используемых настроек. Например, значение переменной ‘b’ было 0,49999999999999994, когда мы использовали компилятор Visual C ++ 2010.
То, что они пытаются сказать, это сравнение чисел с плавающей запятой сложно. Если вы просто присваиваете число с плавающей запятой, сохраняйте его и перемещайте по памяти, чтобы потом сравнить с собой в этой функции — не стесняйтесь отклонять это сообщение об ошибке.
Если вы хотите выполнить некоторую проверку битового представления (что, честно говоря, вы делаете), увидеть ниже.
Если вы выполняете какие-то масштабные вычисления для чисел с плавающей запятой, и вы являетесь разработчиком игры, вычисляя координаты вражеских линейных крейсеров — это предупреждение является одним из ваших лучшие друзья.
В любом случае, вернемся к вашему делу. Как это обычно бывает с PVS-Studio, они не увидели точную ошибку, но указали вам верное направление. Вы на самом деле хочу сравнить два значения с плавающей точкой, но вы делаете это неправильно. Дело в том, что если оба сравниваемых числа с плавающей запятой содержат NaN (даже в одном и том же битовом представлении), вы получите *dest != value
, и ваш код не будет работать так, как вы хотите.
В этом случае лучше переосмыслить память под float *
как uint32_t
(или любой другой целочисленный тип имеет тот же размер, что и float
на вашей цели) и сравнить их вместо.
Например, в вашем конкретном случае, register_file_->values[register_name]
имеет тип xe::gpu::RegisterFile::RegisterValue
, который уже поддерживает uint32_t
представление.
Как побочный эффект, это уберет предупреждение 🙂
Других решений пока нет …