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

V2661. MISRA. A 'for' loop should be well-formed.

24 Сен 2025

Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.

Правило актуально только для языка C.

Цикл for должен быть отформатирован в соответствии со следующими правилами:

Первый оператор цикла (Init-statement) должен:

  • либо быть пустым;
  • либо не иметь постоянных побочных эффектов;
  • либо определять и инициализировать счётчик цикла.

Второй оператор (Condition) должен:

  • не иметь постоянных побочных эффектов;
  • использовать счётчик или его же совместно с флагом управления циклом;
  • не использовать объекты, которые модифицируются в теле цикла.

Третий оператор цикла (Expression) должен:

  • не иметь постоянных побочных эффектов, кроме модификации счетчика цикла;
  • не использовать объекты, которые модифицируются в теле цикла.

Соблюдение правил оформления циклов for снижает вероятность ошибок, а также упрощает процесс отладки и обзора кода. Такой подход позволяет сразу видеть всю логику работы цикла в его заголовке, исключая непредсказуемое поведение.

Примечание. Допустимо использовать цикл с тремя пустыми операторами for( ; ; ).

Рассмотрим пример некорректного кода:

for (size_t i = 0;
     i < users.size() && retry_count < MAX_RETRIES; // <=
     i += (retry_count > 0 ? 0 : 1))                // <=
{
  if (!checkUser(users[i])) 
  {
    retry_count += 1;        // <=
  } 
  else
  {
    retry_count = 0;         // <=
  }
  // ....
}

Опасность кода заключается в неочевидном зависании цикла на проблемном пользователе. Если функция checkUser постоянно возвращает false при обработке какого-то пользователя, цикл застревает на одной позиции, пока не исчерпает все попытки. Это приводит к пропуску всех последующих пользователей, что бывает сложно обнаружить при обзоре кода.

В данном случае правильное форматирование запрещает использование retry_count во втором и третьем операторе цикла for, поскольку эта переменная модифицируется в теле цикла. Чтобы исправить проблему, можно вынести механизм валидации в отдельную функцию. Тогда цикл будет работать предсказуемо и обрабатывать всех пользователей.

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

bool checkUserWithRetry(const std::string& user) {
    for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
        if (checkUser(user)) return true;
    }
    return false;
}
// ....
for (size_t i = 0; i < users.size(); i++) {
    if (!checkUserWithRetry(users[i])) {
        logError("Failed to process user: " + users[i]);
    }
}
// ....

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

  • MISRA-C-2023-14.2