Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top

Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12

>
>
>
V3191. Iteration through collection mak…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V3191. Iteration through collection makes no sense because it is always empty.

30 Июн 2023

Анализатор обнаружил попытку обхода пустой коллекции. Такая операция не имеет смысла: скорее всего, код содержит ошибку.

Рассмотрим пример:

private List<Action> _actions;
....
public void Execute()
{
  var remove = new List<Action>();
  foreach (var action in _actions)
  {
    try
    {
      action.Invoke();
    }
    catch (Exception ex)
    {
      Logger.LogError(string.Format("Error invoking action:\n{0}", ex));
    }
  }
  foreach (var action in remove)
    _actions.Remove(action);
}

Метод 'Execute' поочередно вызывает делегаты из списка '_actions', а также ловит и логирует возникающие в процессе выполнения ошибки. Помимо основного цикла, в конце метода есть еще один, который должен удалять из списка '_actions' делегаты, хранящиеся в коллекции 'remove'.

Проблема здесь в том, что коллекция 'remove' всегда будет пустой. Она создается в самом начале метода, но не заполняется в процессе. Таким образом, последний цикл никогда не будет выполнен.

Корректная реализация метода может выглядеть следующим образом:

public void Execute()
{
  var remove = new List<Action>();
  foreach (var action in _actions)
  {
    try
    {
      action.Invoke();
    }
    catch (Exception ex)
    {
      Logger.LogError(string.Format("Error invoking action:\n{0}", ex));
      remove.Add(action);
    }
  }
  foreach (var action in remove)
    _actions.Remove(action);
}

Теперь добавляем в коллекцию 'remove' делегаты, при исполнении которых возникли исключения, чтобы впоследствии удалить их.

Анализатор также может выдать предупреждение на вызов метода, выполняющего обход коллекции.

Рассмотрим пример:

int ProcessValues(int[][] valuesCollection,
                  out List<int> extremums)
{
  extremums = new List<int>();

  foreach (var values in valuesCollection)
  {
    SetStateAccordingToValues(values);
  }
  return extremums.Sum();
}

Метод 'ProcessValues' принимает массивы чисел для обработки. В данном случае нас интересует коллекция 'extremums': она создается пустой и не заполняется в процессе выполнения метода. При этом 'ProcessValues' возвращает результат вызова метода 'Sum' на коллекции 'extremums'. Код выглядит ошибочным, так как вызов 'Sum' всегда возвращает 0.

Корректная реализация метода может выглядеть следующим образом:

int ProcessValues(int[][] valuesCollection,
                  out List<int> extremums)
{
  extremums = new List<int>();

  foreach (var values in valuesCollection)
  {
    SetStateAccordingToValues(values);
    extremums.Add(values.Max());
  }
  return extremums.Sum();
}
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

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

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

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

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

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

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


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам