>
>
>
V105. N operand of '?:' operation: impl…


V105. N operand of '?:' operation: implicit type conversion to memsize type.

Анализатор обнаружил потенциально возможную ошибку внутри арифметического выражения, связанную с неявным приведением к типу memsize. Ошибка переполнения может быть связана с изменением допустимого интервала значений переменных, входящих в выражение. Данное предупреждение практически эквивалентно предупреждению V104, за тем исключением, что неявное приведение типа возникает за счет использования операции '?:'.

Приведем пример неявного приведения типов при использовании операции:

int i32;
float f = b != 1 ? sizeof(int) : i32;

В арифметическом выражении используется тернарная операция '?:', имеющая три операнда:

  • b != 1 - первый операнд;
  • sizeof(int) - второй операнд;
  • i32 - третий операнд.

Результатом выражения "b != 1 ? sizeof(int) : i32" является значение типа 'size_t', которое затем преобразуется в значение типа 'float'. Таким образом, неявное приведение типа осуществляется для 3-его операнда операции '?:'.

Рассмотрим пример некорректного кода:

bool useDefaultVolume;
size_t defaultVolume;
unsigned width, height, depth;
...
size_t volume = useDefaultVolume ?
                        defaultVolume :
                        width * height * depth;

Предположим, мы разрабатываем приложение численного моделирования, для которого требуется трехмерная счетная область. Количество используемых счетных элементов определяется в зависимости от значения переменной 'useDefaultSize' и задается по умолчанию или произведением длинны, высоты и глубины счетной области. На 32-битной платформе объем уже выделенной памяти не может превышать 2-3 Гб (в зависимости от версии ОС Windows) и, соответственно, результат выражения "width * height * depth" всегда будет корректен. На 64-битной платформе, пользуясь возможностью работать с большим объемом памяти, количество счетных элементов может превысить значение 'UINT_MAX' (4 Гб). В этом случае произойдет переполнение при вычислении выражения "width * height * depth", так как результат этого выражения имеет тип 'unsigned'.

Исправление кода может заключаться в изменении типа переменных 'width', 'height' и 'depth' на memsize тип, как показано ниже:

...
size_t width, height, depth;
...
size_t volume = useDefaultVolume ?
                        defaultVolume :
                        width * height * depth;

Или использовании явного приведения типов:

unsigned width, height, depth;
...
size_t volume = useDefaultVolume ?
                        defaultVolume :
         size_t(width) * size_t(height) * size_t(depth);

Дополнительно мы рекомендуем изучить описание аналогичного предупреждения V104, где можно ознакомиться с другими эффектами неявного приведения к типу memsize.

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