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


> Это правило входит в группу "Диагностика 64\\\-битных ошибок"\\\. Разработка правил этой группы больше не ведётся, и в будущем они могут быть отключены\\\. Если вы используете эти правила, \[свяжитесь с нашей поддержкой\]\(https://pvs\-studio\.ru/ru/about\-feedback/\) — мы поможем найти замену или предложим альтернативное решение\\\.

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

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

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

```cpp
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' [неявно приводится](https://pvs-studio.ru/ru/blog/terms/0021/) к memsize типу \(которым в данном случае является тип 'INT\_PTR'\)\. Получив такое предупреждение, вы можете исправить ошибку, изменив тип 'int' на более подходящий\.

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

```cpp
void SetAt(int nIndex, ARG_TYPE newElement);
```

А в новой:

```cpp
void SetAt(INT_PTR nIndex, ARG_TYPE newElement);
```

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

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

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

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

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

```cpp
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'\.

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

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

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

Если вы точно уверены, что неявное приведение типа фактического аргумента функции совершенно корректно, то для подавления предупреждения анализатора вы можете использовать [явное приведение типа](https://pvs-studio.ru/ru/blog/terms/0015/), как показано ниже:

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

Иногда явное приведение типа может маскировать ошибку\. В этом случае вы можете воспользоваться правилом [V201](https://pvs-studio.ru/ru/docs/warnings/v201/)\.

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

1. 64\-битные уроки\. Урок 17\. Паттерн 9\. [Смешанная арифметика](https://pvs-studio.ru/ru/blog/lessons/0017/)\.