CERT C++: PRE31-C

Избегайте побочных эффектов в аргументах к небезопасным макросам

Описание

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

Избегайте побочных эффектов в аргументах к небезопасным макросам.[1]

Реализация Polyspace

Эта проверка проверяет наличие побочного эффекта в аргументах на небезопасный макрос.

Примеры

расширить все

Проблема

Побочный эффект в аргументах к небезопасному макросу возникает, когда вы вызываете небезопасный макрос с выражением, которое имеет побочный эффект.

  • Небезопасный макрос: При расширении небезопасный макрос оценивает свои аргументы несколько раз или вообще не оценивает свой аргумент.

    Для образца, ABS macro оценивает его аргумент x дважды.

    #define ABS(x) (((x) < 0) ? -(x) : (x))

  • Побочный эффект: При оценке выражение со побочным эффектом изменяет по крайней мере одну из переменных в выражении.

    Для образца, ++n изменяет n, но n+1 не изменяет n.

    Чекер не рассматривает побочные эффекты во вложенных макросах. Проверка также не рассматривает вызовы функций или нестабильный доступ к переменным в качестве побочных эффектов.

Риск

Если вы вызываете небезопасный макрос с выражением, которое имеет побочный эффект, выражение оценивается несколько раз или не оценивается вообще. Побочный эффект может возникнуть несколько раз или вообще не возникнуть, вызывая неожиданное поведение.

Например, в вызове MACRO(++n)ожидается только один шаг переменной n. Если MACRO является небезопасным макросом, шаг происходит более одного раза или не происходит вообще.

Шашка помечает выражения со побочными эффектами в assert макрос, потому что assert макрос отключен в неотладке. Чтобы скомпилироваться в неотладке, вы задаете NDEBUG макрос во время компиляции. Например, в GCC вы используете флаг -DNDEBUG.

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

Вычислите выражение с побочным эффектом в отдельном операторе, а затем используйте результат как аргумент макроса.

Для образца вместо:

MACRO(++n);
Выполните операцию в два этапа:
++n;
MACRO(n);
Также используйте встроенную функцию вместо макроса. Передайте выражение с побочным эффектом как аргумент встроенной функции.

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

Пример - Аргумент макроса с побочными эффектами
#define ABS(x) (((x) < 0) ? -(x) : (x))
  
void func(int n) {
  /* Validate that n is within the desired range */
  int m = ABS(++n);
 
  /* ... */
}

В этом примере ABS макрос оценивает его аргумент дважды. Вторая оценка может привести к непреднамеренному шагу.

Коррекция - отдельная оценка выражения от использования макроса

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

#define ABS(x) (((x) < 0) ? -(x) : (x))
  
void func(int n) {
  /* Validate that n is within the desired range */
  ++n;
  int m = ABS(n);
 
  /* ... */
}
Коррекция - Вычисление выражения в встроенной функции

Другой возможной коррекцией является вычисление выражения в встроенной функции.

static inline int iabs(int x) {
  return (((x) < 0) ? -(x) : (x));
}
  
void func(int n) {
  /* Validate that n is within the desired range */
 
int m = iabs(++n);
 
  /* ... */
}

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

Группа: 49. Разное (MSC)
Введенный в R2019a

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

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

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