exponenta event banner

CERT C: Rec. MSC12-C

Обнаружение и удаление кода, который не действует или никогда не выполняется

Описание

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

Обнаружение и удаление кода, который не действует или никогда не выполняется. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

  • Недоступный код.

  • Мертвый код.

  • Бесполезно, если.

  • Пишите без дальнейшего чтения.

Примеры

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

Проблема

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

Polyspace ® Bug Finder™ и Polyspace Code Prover™ проверки этого правила кодирования по-разному. Анализ может дать различные результаты.

Проверка выполнения программы проверки кода для недостижимого кода показывает больше случаев, чем проверка MISRA ® для этого правила. См. такжеUnreachable code(Доказательство кода Polyspace). Проверка времени выполнения выполняет более полный анализ. В процессе проверки могут отображаться некоторые экземпляры, которые не являются строго недоступными кодом, но недоступны только в контексте анализа. Например, в следующем коде проверка времени выполнения показывает потенциальное деление на ноль в первой строке, а затем удаляет нулевое значение flag для остальной части анализа. Поэтому он считает if блок недоступен.

val=1.0/flag;
if(!flag) {}
Средство проверки MISRA предназначено для предотвращения таких результатов.

Риск

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

  • Он занимает место в памяти целевого компьютера.

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

  • В пределах цикла он может предотвратить нахождение всего цикла в кэше команд.

Пример - Следующий код return Заявление
enum light { red, amber, red_amber, green };
void report_color(enum light);
enum light next_light ( enum light color )
{
    enum light res;

    switch ( color )
    {
    case red:
        res = red_amber;
        break;
    case red_amber:
        res = green;
        break;
    case green:
        res = amber;
        break;
    case amber:
        res = red;
        break;
    default:
    {
        error_handler ();
        break;
    }
    }

    report_color(res);
    return res;
    res = color;     /* Non-compliant */
}

В этом примере правило нарушается, поскольку после return заявление.

Проблема

Проблема возникает, когда анализ обнаруживает доступную операцию, которая не влияет на поведение программы, если операция удалена.

Polyspace Bug Finder обнаруживает бесполезные операции записи во время анализа.

Средство проверки кода Polyspace не обнаруживает бесполезных операций записи. Например, если присвоить значение локальной переменной, но не читать его позже, средство проверки кода Polyspace не обнаружит это бесполезное назначение. Используйте Polyspace Bug Finder для обнаружения таких бесполезных операций записи. Дополнительные сведения см. в разделе MISRA C:2012 в Polyspace Bug Finder.

В программе Code Prover можно также увидеть разницу в результатах на основе выбора опции. Verification level (-to)(Доказательство кода Polyspace). См. раздел Проверка нарушений стандартов кодирования.

Риск

Если операция достижима, но удаление операции не влияет на поведение программы, операция представляет собой мертвый код.

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

Операции с расширением языка, например __asm ( "NOP" ); не считаются мертвым кодом.

Пример - Операции с резервированием
extern volatile unsigned int v;
extern char *p;

void f ( void ) {
    unsigned int x;


    ( void ) v;      /* Compliant - Exception*/
    ( int ) v;       /* Non-compliant  */
    v >> 3;          /* Non-compliant  */

    x = 3;           /* Non-compliant - Detected in Bug Finder only */

    *p++;            /* Non-compliant  */
    ( *p )++;        /* Compliant  */
}

В этом примере правило нарушается при выполнении операции с переменной, но результат этой операции не используется. Например,

  • Операции (int) и >> на переменной v являются избыточными, поскольку результаты не используются.

  • Операция = является избыточным, поскольку локальная переменная x не считывается после операции.

  • Операция * на p++ является избыточным, поскольку результат не используется.

Правило не нарушается, если:

  • Переменная приводится к void. Приведение указывает на то, что вы намеренно не используете значение.

  • Используется результат операции. Например, операция * на p не является избыточным, поскольку *p увеличивается.

Проблема

Эта проблема возникает на if- операторы, в которых условие всегда истинно. Этот дефект возникает только для операторов if, не имеющих операторов else.

Этот дефект не является необходимым if-statements, когда нет разницы в выполнении кода, если if-статия удалена.

Риск

Ненужный if операторы часто указывают на ошибку кодирования. Возможно, if состояние закодировано неправильно или if оператор не требуется вообще.

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

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

Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.

См. примеры исправлений ниже.

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

Пример - if с перечисляемым типом
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);

void bridge(void)
{
    suit card = nextcard();
    if ((card < SPADES) || (card > CLUBS)){
        card = UNKNOWN_SUIT;
    }

    if (card < 7) {
        do_something(card);
    }
}

Тип suit перечисляется с пятью параметрами. Однако условное выражение card < 7 всегда вычисляется как true, потому что card может быть не более 5. if инструкция не нужна.

Исправление 1 - Изменение условия

Одной из возможных корректировок является изменение условия if в коде. В этой коррекции 7 изменяется на UNKNOWN_SUIT непосредственно относится к типу card.

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);

void bridge(void)
{
    suit card = nextcard();
    if ((card < SPADES) || (card > CLUBS)){
        card = UNKNOWN_SUIT;
    }

    if (card > UNKNOWN_SUIT) {
        do_something(card);
    }
}
Исправление - удалить, если

Другой возможной поправкой является удаление условия if в коде. Поскольку условие всегда соответствует действительности, его можно удалить, чтобы упростить код.

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);

void bridge(void)
{
    suit card = nextcard();
    if ((card < SPADES) || (card > CLUBS)){
        card = UNKNOWN_SUIT;
    }

    do_something(card);
}
Проблема

Эта проблема возникает, когда значение, назначенное переменной, никогда не читается.

Например, вы записываете значение в переменную, а затем записываете второе значение перед прочтением предыдущего значения. Первая операция записи является избыточной.

Риск

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

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

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

Если определено, что операция записи является избыточной, удалите операцию.

Пример - Запись без дополнительной ошибки чтения
void sensor_amplification(void)
{
    extern int getsensor(void);
    int level;

    level = 4 * getsensor();            
    /* Defect: Useless write */
}

После переменной level получает назначенное значение 4 * getsensor(), он не читается.

Коррекция - использовать значение после присвоения

Одной из возможных корректировок является использование переменной. level после назначения.

#include <stdio.h>

void sensor_amplification(void)
{
    extern int getsensor(void);
    int level;

    level = 4 * getsensor(); 
    
    /* Fix: Use level after assignment */
    printf("The value is %d", level);
    
}

Переменная level распечатывается, читая новое значение.

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

Группа: Rec. 48. Разное (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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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