exponenta event banner

CERT C: Rec. PRE10-C

Перенос многостадийных макросов в цикл do-while

Описание

Определение правила

Заключите многостатийные макросы в цикл do-while. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие макроса с несколькими инструкциями.

Примеры

развернуть все

Проблема

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

Риск

Расширение макроса в определенных контекстах, таких как if условие или цикл, может привести к непреднамеренной программной логике.

Например, рассмотрим макрос:

#define RESET(x,y) \
   x=0; \
   y=0;
В if оператор, такой как:
if(checkSomeCondition)
   RESET(x,y);
макрос расширяется до:
if(checkSomething)
   x=0;
y=0;
которые могут быть неожиданными, если требуется выполнить обе инструкции в if блок.

Зафиксировать

В определении макроса заключите несколько операторов в do...while(0) цикл.

Например, в предыдущем примере используйте определение:

#define RESET(x,y) \
   do { \
     x=0; \
     y=0; \
   } while(0)
Этот макрос подходит для расширения во всех контекстах. while(0) обеспечивает выполнение инструкций только один раз.

Можно также использовать встроенные функции в качестве предпочтения функциональным макросам, включающим несколько операторов.

Обратите внимание, что цикл необходим для правильного решения, и перенос инструкций только в фигурные скобки не устраняет проблему. Расширение макроса может привести к непреднамеренному коду.

Пример - Макрос с несколькими операторами
#define RESET(x,y) \
   x=0; \
   y=0;

void func(int *x, int *y, int resetFlag){
    if(resetFlag)
        RESET(x,y);    
}

В этом примере дефект возникает из-за макроса RESET состоит из нескольких операторов.

Исправление - перенос нескольких операторов макроса в do-while Петля

Переносить операторы макроса в do..while(0) цикл в определении макроса.

#define RESET(x,y) \
   do { \
     x=0; \
     y=0; \
   } while(0)

void func(int *x, int *y, int resetFlag){
    if(resetFlag)
        RESET(x,y);    
}

Проверить информацию

Группа: Rec. 01. Препроцессор (PRE)
Представлен в R2020a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.