CERT C: Rule PRE31-C

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

Описание

Управляйте определением

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

Реализация Polyspace

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

Примеры

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

Проблема

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

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

    Например, ABS макрос оценивает свой аргумент 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);
 
  /* ... */
}

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

Группа: правило 01. Препроцессор (PRE)
Введенный в R2019a

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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