CERT C++: PRE31-C

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

Описание

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

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

Примеры

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

Описание

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

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

    Например, макрос 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);
 
  /* ... */
}

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

Группа: 49. Разное (MSC)

Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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