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

Не полагайтесь на побочные эффекты в операндах к sizeof, _Alignof, или _Generic

Описание

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

Не полагайтесь на побочные эффекты в операндах к sizeof, _Alignof, или _Generic. [1]

Примеры

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

Описание

Побочный эффект проигнорированного выражения происходит, когда sizeof, _Alignof или оператор _Generic работают с выражением с побочным эффектом. Когда оценено, выражение с побочным эффектом изменяет по крайней мере одну из переменных в выражении.

Например, дефектное средство проверки не делает флага sizeof(n+1), потому что n+1 не изменяет n. Средство проверки отмечает sizeof(n++), потому что n++ предназначается, чтобы изменить n.

Проверка также применяется к оператору C++ alignof и его расширения C, __alignof__ и __typeof__.

Риск

Выражение в _Alignof или операторе _Generic не выполнено. Выражение в операторе sizeof выполнено, только если оно требуется для вычисления размера массива переменной длины, например, sizeof(a[n++]).

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

Фиксация

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

Например, вместо:

a = sizeof(n++);
выполните операцию на двух шагах:
n++;
a = sizeof(n);

Средство проверки рассматривает вызов функции как выражение с побочным эффектом. Даже если функция не имеет побочных эффектов теперь, она может иметь побочные эффекты на более поздних сложениях. Код более удобен в сопровождении, если вы вызываете функцию вне оператора sizeof.

Пример - инкрементный оператор в sizeof

#include <stdio.h>

void func(void) {
    unsigned int a = 1U;
    unsigned int b = (unsigned int)sizeof(++a);
    printf ("%u, %u\n", a, b);
}

В этом примере sizeof работает с ++a, который предназначается, чтобы изменить a. Поскольку выражение не выполнено, модификации не происходит. Оператор printf показывает, что a все еще имеет значение 1.

Исправление — выполняет шаг вне sizeof

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

#include <stdio.h>

void func(void) {
    unsigned int a = 1U;
    ++a;
    unsigned int b = (unsigned int)sizeof (a); 
    printf ("%u, %u\n", a, b);
}

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

Группа: правило 03. Выражения (EXP)

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

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