exponenta event banner

CERT C: FIO41-C правил

Не вызывайте getc (), putc (), getwc () или putwc () с аргументом stream, имеющим побочные эффекты

Описание

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

Не вызывайте getc (), putc (), getwc () или putwc () с аргументом stream, имеющим побочные эффекты . [1]

Внедрение Polyspace

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

Примеры

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

Проблема

Аргумент Stream с возможными непреднамеренными побочными эффектами возникает при вызове getc(), putc(), getwc(), или putwc() с аргументом stream, имеющим побочные эффекты.

Аргумент потока с, возможно, непреднамеренными побочными эффектами рассматривает следующее как побочные эффекты потока:

  • Любое назначение переменной потока, например FILE *или любое назначение переменной более глубокого типа потока, такой как массив FILE *.

  • Любой вызов функции, которая управляет потоком или более глубоким типом потока.

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

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

Риск

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

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

Чтобы побочный эффект потока происходил только один раз, используйте отдельный оператор для аргумента потока.

Пример - Аргумент потока getc() Имеет побочный эффект fopen()
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#define fatal_error() abort()

const char* myfile = "my_file.log";

void func(void)
{
    int c;
    FILE* fptr;
    /* getc() has stream argument fptr with
    * 2 side effects: call to fopen(), and assignment
    * of fptr
    */
    c = getc(fptr = fopen(myfile, "r"));
    if (c == EOF) {
        /* Handle error */
        (void)fclose(fptr);
        fatal_error();
    }
    if (fclose(fptr) == EOF) {
        /* Handle error */
        fatal_error();
    }
}

void main(void)
{
    func();

}

В этом примере: getc() вызывается с аргументом stream fptr. Аргумент stream имеет два побочных эффекта: вызов fopen() и присвоение fptr. Если getc() реализуется как небезопасный макрос, побочные эффекты происходят несколько раз.

Исправление - использовать отдельный отчет для fopen()

Одной из возможных корректировок является использование отдельного оператора для fopen(). Вызов fopen() и присвоение fptr в этом утверждении, чтобы не было побочных эффектов при прохождении fptr кому getc().

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#define fatal_error() abort()


const char* myfile = "my_file.log";

void func(void)
{
    int c;
    FILE* fptr;

    /* Separate statement for fopen()
    * before call to getc()
    */
    fptr = fopen(myfile, "r");
    if (fptr == NULL) {
        /* Handle error */
        fatal_error();
    }
    c = getc(fptr);
    if (c == EOF) {
        /* Handle error */
        (void)fclose(fptr);
        fatal_error();
    }
    if (fclose(fptr) == EOF) {
        /* Handle error */
        fatal_error();
    }
}

void main(void)
{
    func();

}

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

Группа: Правило 09. Входной выход (FIO)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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