V104. Implicit type conversion to memsize type in an arithmetic expression.
Анализатор обнаружил потенциально возможную ошибку внутри арифметического выражения, связанную с неявным приведением к типу memsize. Ошибка переполнения может быть связана с изменением допустимого интервала значений переменных, входящих в выражение.
Первый пример.
Некорректные выражения сравнения. Рассмотрим код:
size_t n;
unsigned i;
// Infinite loop (n > UINT_MAX).
for (i = 0; i != n; ++i) { ... }
В примере показана ошибка, связанная с неявным приведением типа 'unsigned' к типу 'size_t' при выполнении операции сравнения.
На 64-битной платформе у вас может появиться возможность обрабатывать больший объем данных, и значение переменной 'n' может превысить число 'UINT_MAX' (4 Гб). В результате, условие "i != n" всегда будет истинно, что приведет к вечному циклу.
Пример исправленного кода:
size_t n;
size_t i;
for (i = 0; i != n; ++i) { ... }
Второй пример.
char *begin, *end;
int bufLen, bufCount;
...
ptrdiff_t diff = begin - end + bufLen * bufCount;
Неявное приведение типа 'int' к типу 'ptrdiff_t' зачастую служит признаком ошибки. Следует обратить внимание, что приведение происходит не при выполнении оператора "=" (так как выражение "begin - end + bufLen * bufCount" имеет тип 'ptrdiff_t'), а внутри этого выражения. Подвыражение "begin - end" согласно правилам языка С++ имеет тип 'ptrdiff_t', а правая "bufLen * bufCount" тип 'int'. При переходе на 64-битную платформу программа может начать обрабатывать больший объем данных, в результате чего может произойти переполнение при вычислении подвыражения "bufLen * bufCount".
Следует изменить тип переменных 'bufLen' и 'bufCount' на memsize тип или использовать явное приведение типа, как показано на примере:
char *begin, *end;
int bufLen, bufCount;
...
ptrdiff_t diff = begin - end +
ptrdiff_t(bufLen) * ptrdiff_t(bufCount);
Отметим, что неявное приведение к типу memsize внутри выражений не всегда является ошибочным. Рассмотрим следующую ситуацию:
size_t value;
char c1, c2;
size_t result = value + c1 * c2;
Анализатор не выдает сообщения, хотя здесь происходит приведение типа 'int' к 'size_t', так как при вычислении подвыражения "c1 * c2" переполнения произойти не может.
Если вы подозреваете в программе наличие ошибок, связанных с некорректным явным приведением типов в выражениях, то Вы можете воспользоваться правилом V201. Пример ситуации, при которой явное приведение типа к 'size_t' скрывает ошибку, представлен ниже:
int i;
size_t st;
...
st = size_t(i * i * i) * st;
Дополнительные материалы по данной теме:
- 64-битные уроки. Урок 17. Паттерн 9. Смешанная арифметика.