Анализатор обнаружил потенциальную ошибку при работе с контейнером фиксированного размера. Эту диагностику нам предложил реализовать один из наших пользователей. Вот как он сформулировал задачу.
Для работы с массивами константного размера мы используем следующий шаблонный класс:
template<class T_, int numElements > class idArray { public: int Num() const { return numElements; }; ..... inline const T_ & operator[]( int index ) const { idassert( index >= 0 ); idassert( index < numElements ); return ptr[index]; }; inline T_ & operator[]( int index ) { idassert( index >= 0 ); idassert( index < numElements ); return ptr[index]; }; private: T_ ptr[numElements]; };
Класс позволяет обнаружить ошибки выхода за пределы массива при запуске DEBUG версии. При этом производительность RELESE версии не снижается. Пример некорректного кода:
idArray<int, 1024> newArray; newArray[-1] = 0; newArray[1024] = 0;
Ошибки будут обнаружены при запуске отладочной версии. Однако хочется иметь возможность обнаруживать подобные ошибки с помощью статического анализа ещё на этапе компиляции.
Для выявления подобных ошибочных ситуаций и предназначена диагностика V582. Если в программе используется класс, реализующий функциональность контейнера фиксированного размера, то анализатор пытается проверить, что индекс не выходит за его границу. Пример диагностики:
idArray<float, 16> ArrA; idArray<float, 8> ArrB; for (size_t i = 0; i != 16; i++) ArrA[i] = 1.0f; for (size_t i = 0; i != 16; i++) ArrB[i] = 1.0f;
Здесь анализатор выдаст предупреждение:
V582 Consider reviewing the source code which operates the 'ArrB' container. The value of the index belongs to the range: [0..15].
Ошибка в том, что оба цикла обрабатывают 16 элементов, хотя второй массив содержит только 8 элементов. Корректный вариант:
for (size_t i = 0; i != 16; i++) ArrA[i] = 1.0f; for (size_t i = 0; i != 8; i++) ArrB[i] = 1.0f;
Следует отметить, что передача слишком больших или маленьких индексов не всегда означает ошибку в программе. Например, оператор [] может быть реализован следующим образом:
inline T_ & operator[]( int index ) { if (index < 0) index = 0; if (index >= numElements) index = numElements - 1; return ptr[index]; };
Если вы используете подобные классы и получаете много ложных срабатываний, то очевидно вам следует отключить диагностику V582.
Примечание. Анализатор не обладает искусственным интеллектом и поэтому его возможности поиска дефектов при работе с контейнерами ограничены. Мы работаем над усовершенствованием алгоритмов, поэтому если вы заметили явные ложные срабатывания или наоборот ситуации, в которых анализатор не выдал предупреждение, просим написать нам и прислать соответствующий пример кода.
Данная диагностика классифицируется как: