CERT C: правило MSC38-C

Не обрабатывайте предопределенный идентификатор как объект, если это может только быть реализовано как макрос

Описание

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

Не обрабатывайте предопределенный идентификатор как объект, если это может только быть реализовано как макрос. [1]

Примеры

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

Описание

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

Например, вы отсылаете к внешней переменной errno:

extern int errno;
Однако errno не происходит как переменная, но макрос.

Дефект применяется к ним макросы: assert, errno, math_errhandling, setjmp, va_arg, va_copy, va_end и va_start. Средство проверки ищет дефект только в исходных файлах (не заголовочные файлы).

Риск

Стандарт C11 (Секунда. 7.1.4), позволяет вам переопределять большинство макросов как объекты. Чтобы получить доступ к объекту а не макросу в исходном файле, вы делаете один из них:

  • Повторно объявите идентификатор как внешнюю переменную или функцию.

  • Для подобных функции макросов заключите имя идентификатора в круглые скобки.

При попытке использовать эти стратегии макросов, которые не могут быть переопределены как объекты, ошибка происходит.

Фиксация

Не используйте идентификаторы таким способом, которым подавлено макрорасширение.

  • Не повторно объявляйте идентификаторы как внешние переменные или функции.

  • Для подобных функции макросов не заключайте макро-имя в круглые скобки.

Пример - использование assert как функция

#include<assert.h>
typedef void (*err_handler_func)(int);

extern void demo_handle_err(err_handler_func, int);

void func(int err_code) {
    extern void assert(int);   
    demo_handle_err(&(assert), err_code);
}

В этом примере макрос assert переопределен как внешняя функция. Когда передано в качестве аргумента к demo_handle_err, идентификатор assert заключен в круглые скобки, который подавляет использование макроса assert.

Исправление — использует assert в качестве макроса

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

#include<assert.h>
void demo_handle_err(int err_code) {
    assert(err_code == 0);                   
}

void func(int err_code) {
    demo_handle_err(err_code);          
}

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

Группа: правило 48. Разное (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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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