CERT C++: FIO41-C

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

Описание

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

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

Примеры

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

Описание

Аргумент 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() вызван потоковым аргументом fptr. Потоковый аргумент имеет два побочных эффекта: вызов 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();

}

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

Группа: 07. Ввод-вывод (FIO)

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

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