Для получения триального ключа
заполните форму ниже
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
V1026. The variable is incremented in t…
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Диагностика микро-оптимизаций (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
Оглавление

V1026. The variable is incremented in the loop. Undefined behavior will occur in case of signed integer overflow.

29 Авг 2018

Анализатор обнаружил возможное переполнение знаковой переменной в цикле. Переполнение знаковых переменных приводит к неопределённому поведению.

Пример:

int checksum = 0;
for (....) {
  checksum += ....;
}

Перед нами абстрактный алгоритм подсчёта контрольной суммы. Алгоритм подразумевает возможность переполнения переменной 'checksum'. Однако переменная имеет знаковый тип, а, следовательно, её переполнение приводит к неопределённому поведению. Код некорректен и должен быть модифицирован.

Следует использовать беззнаковые типы, семантика переполнения которых определена.

Корректный код:

unsigned checksum = 0;
for (....) {
  checksum += ...
}

Некоторые программисты считают, что в переполнении знаковых переменных ничего страшного нет и они могут предсказать, как программа будет работать. Это не так. Может происходить всё что угодно.

Давайте рассмотрим, как могут проявляться ошибки этого типа на практике. Разработчик на форуме жалуется, что GCC глючит и неправильно компилирует его код в режиме оптимизации. Он приводит код следующей функции для подсчёта хеша строки:

int foo(const unsigned char *s)
{
  int r = 0;
  while(*s) {
    r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3) ^ (r >> 1);
    s++;
  }
  return r & 0x7fffffff;
}

Претензия разработчика в том, что компилятор не генерирует код для оператора побитового И (&). Из-за этого функция возвращает отрицательные значения, хотя не должна.

Разработчик считает, что это глюк в компиляторе. Но это не так, неправ программист, который написал такой код. Функция работает неправильно из-за того, что в ней возникает неопределённое поведение.

Компилятор видит, что в переменной 'r' считается некоторая сумма. Переполнения переменной 'r' произойти не должно. Иначе это неопределённое поведение, которое компилятор никак не должен рассматривать и учитывать. Итак, компилятор считает, что раз переменная 'r' после окончания цикла не может быть отрицательной, то операция 'r & 0x7fffffff' для сброса знакового бита является лишней и компилятор просто возвращает из функции значение переменной 'r'.

Диагностика V1026 как раз и предназначена для выявления подобных ошибок. Чтобы исправить код, достаточно считать хеш, используя для этого беззнаковую переменную.

Исправленный вариант кода:

int foo(const unsigned char *s)
{
  unsigned r = 0;
  while(*s) {
    r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3) ^ (r >> 1);
    s++;
  }
  return (int)(r & 0x7fffffff);
}

Дополнительные ссылки:

Данная диагностика классифицируется как:

Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно. Хотите узнать подробнее?
Принять