Анализатор обнаружил небезопасное использование типа 'bool' и целочисленного типа вместе в операции побитового И. Проблема в том, что побитовое И вернет 'false' для четных чисел, так как младший разряд всегда равен нулю. Если же привести вручную численный тип к 'bool', то всё будет в порядке.
Рассмотрим синтетический пример:
int foo(bool a)
{
return a ? 0 : 2;
}
....
bool var = ....;
var &= foo(false);
Независимо от начального значения переменной 'var', после выполнения операции '&=' эта переменная будет иметь значение 'false'. Допустим, функция 'foo' вернёт значение 2. Тогда операция 'var & 2' всегда даёт в результате 0, так как возможные значения 'var' это только 0 или 1.
Этот код следует исправить так:
var &= foo(false) != 0;
или же можно изменить и возвращаемое функцией значение:
int foo(bool a)
{
return a ? 0 : 1;
}
Если, например, функция будет возвращать только значения из диапазона [0;1], то всё в порядке, так как мы можем привести их без потерь к bool.
Пример ошибки, найденной с помощью этой диагностики в реальном проекте:
template<class FuncIterator>
bool SetFunctionList( FuncIterator begin, FuncIterator end) {
bool ret = true;
for (FuncIterator itr = begin; itr != end; ++itr) {
const ROOT::Math::IMultiGenFunction *f = *itr;
ret &= AddFunction(*f);
}
return ret;
}
int AddFunction(const ROOT::Math::IMultiGenFunction & func) {
ROOT::Math::IMultiGenFunction *f = func.Clone();
if (!f) return 0;
fFunctions.push_back(f);
return fFunctions.size();
}
Предполагалось, что функция 'SetFunctionList' проверяет валидность переданных ей итераторов и возвращает 'false', если хоть один из них невалидный, иначе 'true'. Но программист допустил ошибку при работе с оператором '&='. Правый аргумент – функция, которая возвращает целое число в диапазоне от 0 до SIZE_MAX. При возвращении чётных чисел из функции 'AddFunction', переменная 'ret' будет обнуляться, хотя должна это делать только для невалидных итераторов.
Исправленная функция 'SetFunctionList', где результат функции 'AddFunction' предварительно приводится к типу 'bool':
template<class FuncIterator>
bool SetFunctionList( FuncIterator begin, FuncIterator end) {
bool ret = true;
for (FuncIterator itr = begin; itr != end; ++itr) {
const ROOT::Math::IMultiGenFunction *f = *itr;
ret &= (bool)AddFunction(*f);
}
return ret;
}
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V1046. |