V106. Implicit type conversion N argument of function 'foo' to memsize type.


Анализатор обнаружил потенциально возможную ошибку, связанную с неявным приведением фактического аргумента функции к memsize типу.

Первый пример.

Программа работает с большими массивами, используя контейнер CArray из библиотеки MFC. На 64-битной платформе количество элементов массиве может превысить значение INT_MAX (2Гб), что приведет к неработоспособности следующего кода:

CArray<int, int> myArray;
...
int invalidIndex = 0;
INT_PTR validIndex = 0;
while (validIndex != myArray.GetSize()) {
  myArray.SetAt(invalidIndex, 123);
  ++invalidIndex;
  ++validIndex;
}

Данный код заполняет все элементы массива myArray значением 123. Он выглядит совершенно корректно, и вы не получите от компилятора никаких предупреждений, несмотря на его неработоспособность на 64-битной архитектуре. Ошибка заключается в использовании в качестве индекса переменной invalidIndex типа int. Когда значение переменной invalidIndex превысит INT_MAX, произойдет ее переполнение, и оно получит значение равное "-1". Анализатор диагностирует данную ошибку, предупреждая, что первый аргумент функции SetAt неявно приводится к memsize типу (которым в данном случае является тип INT_PTR). Получив такое предупреждение, вы можете исправить ошибку, изменив тип "int" на более подходящий.

Данный пример показателен тем, что обвинять программиста в некачественном коде не очень честно. Дело в том, что в старой версии библиотеки MFC функция SetAt в классе CArray была объявлена следующим образом:

void SetAt(int nIndex, ARG_TYPE newElement);

А в новой:

void SetAt(INT_PTR nIndex, ARG_TYPE newElement);

Даже разработчики Microsoft, создавая MFC, не смогли учесть все возможные последствия использования типа int для индексации в массиве, и можно простить простого разработчика, написавшего такой код.

Приведем исправленный пример:

...
INT_PTR  invalidIndex = 0;
INT_PTR validIndex = 0;
while (validIndex != myArray.GetSize()) {
  myArray.SetAt(invalidIndex, 123);
  ++invalidIndex;
  ++validIndex;
}

Второй пример.

Программа вычисляет необходимый ей размер массива данных, а затем выделяет его с использованием функции malloc, как показано ниже:

unsigned GetArraySize();
...
unsigned size = GetArraySize();
void *p = malloc(size);

Анализатор выдаст предупреждение на строку void *p = malloc(size);. Посмотрев определение функции malloc, мы увидим, что ее формальный аргумент, задающий размер выделяемой памяти, представлен типом size_t. В программе же в качестве фактического аргумента используется переменная size типа unsigned. Если вашей программе на 64-битной архитектуре понадобится массив более UINT_MAX байт (4Гб), то можно с уверенностью утверждать, что приведенный код неверен, так как тип unsigned не может хранить значение более UINT_MAX. Исправление программы заключается в изменении типов переменных и функций, участвующих в вычислении размера массива данных. В приведенном примере необходимо заменить тип unsigned на один из memsize типов, а также, если это необходимо модифицировать код функции GetArraySize.

...
size_t  GetArraySize();
...
size_t size = GetArraySize();
void *p = malloc(size);

Анализатор выдает предупреждения на неявное приведение типа только в том случае, если оно может привести к ошибке при переносе программы на 64-битную платформу. Ниже приведен код, в котором присутствует неявное приведения типов, но которое не вызывает ошибок:

void MyFoo(SSIZE_T index);
...
char c = 'z';
MyFoo(0);
MyFoo(c);

Если вы точно уверены, что неявное приведение типа фактического аргумента функции совершенно корректно, то для подавления предупреждения анализатора вы можете использовать явное приведение типа, как показано ниже:

typedef size_t TYear;
void MyFoo(TYear year);
int year;
...
MyFoo(static_cast<TYear>(year));

Иногда явное приведение типа может маскировать ошибку. В этом случае вы можете воспользоваться правилом V201.

Дополнительные материалы по данной теме:


Найденные ошибки

Проверено проектов
346
Собрано ошибок
13 124

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;