Анализатор обнаружил потенциально возможную ошибку, связанную с тем, что в качестве фактического аргумента в функцию передаётся очень странное значение.
Рассмотрим пример:
bool Matrix4::operator==(const Matrix4& other) const {
if (memcmp(this, &other, sizeof(Matrix4) == 0))
return true;
...
Здесь мы имеем дело с опечаткой. Круглая скобочка поставлена не там, где нужно. К сожалению, это плохо заметно и такая ошибка может очень долго присутствовать в коде. Из-за опечатки размер сравниваемой памяти вычисляется выражением "sizeof(Matrix4) == 0". Так как результат выражение 'false', то сравнивается ноль байт памяти. Корректный вариант:
bool Matrix4::operator==(const Matrix4& other) const {
if (memcmp(this, &other, sizeof(Matrix4)) == 0)
return true;
...
Другой пример. Диагностика определяет случаи, когда массив, состоящий из enum-элементов заполняется с помощью функции 'memset'. При этом подразумевается, что размер элемента не равен одному байту. Такое заполнение будет некорректным, т.к. в этом случае значением заполнится каждый байт, а не каждый элемент массива.
Некорректный код:
enum E { V0, V1, V2, V3, V4 };
E array[123];
memset(array, V1, sizeof(array));
Если компилятор сделает размер каждого элемента равным, например, 4 байта, то все элементы массива будут равны значению 0x01010101, а вовсе не 0x00000001 (V1), как ожидает программист.
Корректный код для заполнения массива:
for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{
array[i] = V1;
}
Или:
std::fill(begin(array), end(array), V1);
Примечание. NULL - странный аргумент.
Иногда программисты пытаются вычислить, сколько требуется выделить памяти под буфер, используя код вот такого типа:
const char* format = getLocalizedString(id, resource);
int len = ::vsprintf(NULL, format, args);
char* buf = (char*) alloca(len);
::vsprintf(buf, format, args);
Учтите, что вызов ::vsprintf(NULL, format, args) некорректен. Вот что про это сказано в MSDN:
int vsprintf(*buffer, char *format, va_list argptr);
....
vsprintf and vswprintf return the number of characters written, not including the terminating null character, or a negative value if an output error occurs. If buffer or format is a null pointer, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions return -1 and set errno to EINVAL.
Данная диагностика учитывает информацию, может ли тот или иной указатель быть нулевым. В ряде случаев, эта информация берется из таблиц разметки функций, которые находятся внутри самого анализатора.
Примером может служить функция 'malloc'. Эта функция может вернуть 'NULL'. Соответственно, если использовать указатель, который вернула функция 'malloc', без предварительной проверки, то это может привести к разыменованию нулевого указателя.
Иногда у наших пользователей возникает желание изменить поведение анализатора и заставить его считать, что, например, функция 'malloc' не может вернуть 'NULL'. Пользователь может использовать системные библиотеки, в которых ситуации нехватки памяти обрабатываются особым образом.
Также может возникнуть желание подсказать анализатору, что определённая функция может вернуть нулевой указатель.
В этом случае вы можете воспользоваться дополнительными настройками, которые описаны в разделе "Как указать анализатору, что функция может или не может возвращать nullptr".
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V575. |