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.
Дополнительные материалы по данной теме:
- 64-битные уроки. Урок 17. Паттерн 9. Смешанная арифметика.