V107. Implicit type conversion N argument of function 'foo' to 32-bit type.


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

Рассмотрим пример кода, в котором реализована функция поиска максимального элемента в массиве:

float FindMaxItem(float *array, int arraySize) {
  float max = -FLT_MAX;
  for (int i = 0; i != arraySize; ++i) {
    float item = *array++;
    if (max < item)
      max = item;
  }
  return max;
}
...
float *beginArray;
float *endArray;
float maxValue = FindMaxItem(beginArray, endArray - beginArray);

Данный код успешно может работать на 32-битной платформе, но не сможет обрабатывать массивы, состоящие более чем из INT_MAX (2Гб) элементов на 64-битной архитектуре. Это ограничение вызвано использованием типа int для аргумента arraySize. Обратите внимание, что код функции выглядит совершенно корректно не только с точки зрения компилятора, но и анализатора. В этой функции отсутствует приведение типов, и невозможно выявить потенциальную проблему.

Анализатор предупредит о неявном приведении memsize типа к 32-битному типу при вызове функции FindMaxItem. Попробуем разобраться, почему это происходит. Согласно правилам языка Си++, результат вычитания одного указателя из другого имеет тип ptrdiff_t. При вызове функции FindMaxItem произойдет неявное приведение типа ptrdiff_t к типу int, в результате чего произойдет потеря старших битов. Это может стать причиной некорректного поведения программы, при обработке большого объема данных.

Правильным решением будет заменить тип int на тип ptrdiff_t, так как он позволит хранить весь диапазон допустимых значений. Исправленный код:

float FindMaxItem(float *array, ptrdiff_t  arraySize) {
  float max = -FLT_MAX;
  for (ptrdiff_t  i = 0; i != arraySize; ++i) {
    float item = *array++;
    if (max < item)
      max = item;
  }
  return max;
}

Анализатор по возможности старается распознать безопасные приведения типов и не выдавать на них предупреждения. Например, анализатор не выдаст предупреждение на вызов функции FindMaxItem в следующем коде:

float Arr[1000];
float maxValue =
   FindMaxItem(Arr, sizeof(Arr)/sizeof(float));

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

extern int nPenStyle
extern size_t nWidth;
extern COLORREF crColor;
...
// Call constructor CPen::CPen(int, int, COLORREF)
CPen myPen(nPenStyle, static_cast<int>(nWidth), crColor);

В том случае, если вы подозреваете наличие в своем коде некорректных явных приведений memsize типов к 32-битным типам, на которые анализатор не выдает предупреждения, то вы можете воспользоваться правилом V202.

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


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

Проверено проектов
344
Собрано ошибок
12 970

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

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

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

goto PVS-Studio;