exponenta event banner

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

Побочные эффекты аргумента потока возникают несколько раз

Описание

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

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

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

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

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

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

Риск

Если функция реализована как небезопасный макрос, аргумент потока может быть вычислен более одного раза, и побочный эффект потока происходит несколько раз. Например, аргумент потока, вызывающий 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();

}

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: Вкл для рукописного кода, выкл для сгенерированного кода
Синтаксис командной строки: STREAM_WITH_SIDE_EFFECT
Воздействие: Низкий
Представлен в R2018a