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)



