メインコンテンツ

意図しない二次的影響の可能性があるストリーム引数

複数回発生するストリーム引数の二次的影響

説明

この欠陥は、二次的影響のあるストリーム引数を使用して getc()putc()getwc()、または putwc() を呼び出した場合に発生します。

[意図しない二次的影響の可能性があるストリーム引数] は、以下をストリームの二次的影響と見なします。

  • FILE * など、ストリームの変数の代入、または FILE * の配列など、より深いストリーム タイプの変数の代入。

  • ストリームまたはより深いストリーム タイプを操作する関数の呼び出し。

報告される欠陥数は検出された二次的影響の数と一致します。マクロとして実装された関数でストリーム引数が複数回評価される場合、二次的影響のある各評価に対して欠陥が報告されます。

マクロとして実装されていないが、別のオペレーティング システムでマクロとして実装される可能性がある関数でも、欠陥が報告されます。

リスク

安全でないマクロとして関数が実装されている場合、ストリーム引数が複数回評価される可能性があり、そのストリームの二次的影響が複数回発生します。たとえば、fopen() を呼び出すストリーム引数では同じファイルを複数回開く可能性があり、これは未指定の動作です。

修正方法

ストリームの二次的影響が 1 回のみ発生するように、ストリーム引数に個別のステートメントを使用します。

すべて展開する

#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();

}

この例では、ストリーム引数 fptr を使用して getc() が呼び出されています。このストリーム引数には、fopen() の呼び出しと fptr の代入という 2 つの二次的影響があります。安全でないマクロとして getc() が実装されている場合、二次的影響が複数回発生します。

修正 — fopen() に個別のステートメントを使用

1 つの修正方法として、fopen() に個別のステートメントを使用します。fopen() の呼び出しと fptr の代入はこのステートメントで発生するため、fptrgetc() に渡すときに二次的影響がありません。

#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
影響度: Low

バージョン履歴

R2018a で導入