ERR01-C. errno ではなく ferror() を使って FILE ストリームエラーを検査する
ファイルストリームにエラーが発生したかどうかを検査する場合は、errno
ではなく ferror()
を使うこと(たとえば、stdio
関数群を複数回呼び出した後など)。ferror()
関数は、指定されたストリームのエラー表示子を判定し、ストリームのエラー表示子がセットされている場合、そしてその場合に限り、0以外の値を返す。
違反コード
stdio
関数群の実装の多くは、 stdout
が端末の場合に少しだけ動作が変わる。端末かどうかを判定するために、これらの実装は stdout
が端末でない場合に失敗となる(ENOTTY
が返される)何らかの処理を実行する。出力操作は正常に終了しても、errno
は ENOTTY
のままである。この動作はやや混乱を招く可能性があるが、プログラムにとっては、errno
の値はエラーが報告された後にのみ意味を持つため、厳密には間違いではない。より正確にいうと、errno
は、エラー時に errno
を設定するライブラリ関数がエラーコードを返した後にのみ意味を持つ。
errno = 0; printf("This\n"); printf("is\n"); printf("a\n"); printf("test.\n"); if (errno != 0) { fprintf(stderr, "printf failed: %s\n", strerror(errno)); }
適合コード
以下の解決法は、ferror()
を使用してエラーを検出している。また、ある printf()
が操作に失敗したとして、その後の printf()
が(操作に失敗したかどうかに関係なく)errno
を変更している可能性があるため、一連のライブラリ関数の呼び出しが全て終了した後では、最初に失敗した原因を正しく特定できない。
printf("This\n"); printf("is\n"); printf("a\n"); printf("test.\n"); if (ferror(stdout)) { fprintf(stderr, "printf failed\n"); }
リスク評価
ライブラリ関数を複数回呼び出した後で errno
を検査すると、誤ったエラーが報告される可能性があり、結果として誤ったプログラム動作を引き起こす可能性がある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
ERR01-C |
低 |
中 |
低 |
P6 |
L2 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
ECLAIR |
1.1 |
stlibuse |
実装済み |
関連するガイドライン
CERT C++ Secure Coding Standard | ERR01-CPP. Use ferror() rather than errno to check for FILE stream errors |
参考資料
[Horton 1990] | Section 14, p. 254 |
[Koenig 1989] | Section 5.4, p. 73 |
翻訳元
これは以下のページを翻訳したものです。
ERR01-C. Use ferror() rather than errno to check for FILE stream errors (revision 45)