Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V3218. Loop condition may be incorrect due to an off-by-one error.

01 Апр 2025

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

Рассмотрим пример с циклом for:

void PrintArray(int[] numbers)
{
  for (int i = 0; i <= numbers.Length; i++) 
  {
    Console.WriteLine(numbers[i]);
  }
}

Условие цикла i <= numbers.Length охватывает диапазон индексов от 0 до numbers.Length включительно. Первый индекс — 0, значение индекса последнего элемента равноnumbers.Length - 1. Следовательно, значение numbers.Length на единицу превысит индекс последнего элемента коллекции, что приведёт к выходу за пределы массива.

Корректный код выглядит так:

void PrintArray(int[] numbers)
{
  for (int i = 0; i < numbers.Length; i++) 
  {
    Console.WriteLine(numbers[i]);
  }
}

Рассмотрим пример с обратным перебором массива:

void PrintArray(int[] numbers)
{
  for (int i = numbers.Length - 1; i > 0; i--) 
  {
    Console.WriteLine(numbers[i]);
  }
}

Поскольку условие i > 0 ограничивает индекс значением 1, первый элемент массива не будет выведен в консоль.

Корректный код в таком случае будет следующим:

void PrintArray(int[] numbers)
{
  for (int i = numbers.Length - 1; i >= 0; i--) 
  {
    Console.WriteLine(numbers[i]);
  }
}

Теперь условие цикла составлено правильно, и все элементы массива будут выведены в консоль.

Диагностика также охватывает циклы while и do while.

Рассмотрим пример с циклом while:

void PrintArray(List<int> numbersList)
{
  int i = 0;
  while (i <= numbersList.Count)
  {
    Console.WriteLine(numbersList[i]);
    i++;
  }
}

Условие цикла включает значение индекса, равное размеру коллекции. Это приведёт к выходу за границы коллекции.

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

void PrintArray(List<int> numbersList)
{
  int i = 0;
  while (i < numbersList.Count)
  {
    Console.WriteLine(numbersList[i]);
    i++;
  }
}

После исправления коллекция будет перебрана полностью, а исключения не возникнет.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки переполнения буфера (записи или чтения за пределами выделенной для буфера памяти).

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