プログラミング、リファクタリング、そしてすべてにおける究極の疑問: No. 20

同カテゴリーの次の記事

OpenMP* 5.0 TR7 の仕様抜粋訳

この記事は、インテル® デベロッパー・ゾーンに公開されている「The Ultimate Question of Programming, Refactoring, and Everything」の日本語参考訳です。


20. ファイルの終わり (EOF) チェックだけでは不十分な場合がある

SETI@home プロジェクトから抜粋した以下のコードについて考えてみます。このエラーは、次の PVS-Studio 診断によって検出されます。

V663 Infinite loop is possible. The ‘cin.eof()’ condition is insufficient to break from the loop. Consider adding the ‘cin.fail()’ function call to the conditional expression. (V663 無限ループの可能性があります。’cin.eof()’ 条件はループから抜け出すのには不十分です。条件式に ‘cin.fail()’ 関数呼び出しを追加することを検討してください。)

template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b) 
{
  ....
  while (!i.eof()) 
  {
    i >> tmp;
    buf+=(tmp+' ');
  }
  ....
}

説明

ストリーム・オブジェクトからデータを読み取る操作は、一見するよりも単純ではありません。ストリームからデータを読み取る場合、プログラマーは通常 eof() メソッドを呼び出して、ストリームの終わりに到達したかどうかをチェックします。ただし、このチェックは十分ではなく、特定の問題につながるデータ読み取りエラーやストリームの整合性エラーを確認できないため、適切ではありません。

注: ここで提供する情報は、入力ストリームと出力ストリームの両方を考慮しています。繰り返しを避けるため、ここでは 1 つのストリームタイプについてのみ述べます。

これはまさに上記のコード例における問題です。データ読み取りエラーが発生した場合、eof() メソッドは常に false を返すため、無限ループになります。さらに、不明な値が tmp 変数に渡されるため、ループで不正なデータが処理されます。

このような問題を回避するため、追加のメソッド bad()fail() を使用してストリームの状態をチェックする必要があります。

正しいコード

ストリームは暗黙的に bool 型にキャストできることを利用します。true 値は、値が正常に読み取られたことを示します。このコードの動作については、Stack Overflow に詳しい説明 (英語) があります。

template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b) 
{
  ....
  while (i >> tmp) 
  {
    buf+=(tmp+' ');
  }
  ....
}

推奨事項

ストリームからデータを読み取る場合、eof() メソッドだけを使用するのではなく、エラーもチェックするようにします。

bad() メソッドと fail() メソッドを使用して、ストリームの状態をチェックします。bad() メソッドはストリームの整合性をチェックし、fail() メソッドはデータの読み取りエラーをチェックします。

ただし、正しいコード例に示すように bool() 演算子を使用するほうが簡単です。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事

  • Parallel Universe マガジンParallel Universe マガジン Parallel Universe へようこそ。 米国インテル社が四半期に一度オンラインで公開しているオンラインマガジンです。インテルの技術者によるテクノロジーの解説や、最新ツールの紹介など、並列化に関する記事を毎号掲載しています。第1号からのバックナンバーを PDF 形式で用意しました、ぜひご覧ください。 12 […]
  • 比較関数の罠比較関数の罠 この記事は、インテル® デベロッパー・ゾーンに公開されている「The Evil within the Comparison Functions」の日本語参考訳です。 この記事の PDF […]
  • インテル® AVX 命令を使用した complex float データ型の IIR フィルターの実装インテル® AVX 命令を使用した complex float データ型の IIR フィルターの実装 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Intel® AVX Realization Of IIR Filter For Complex Float Data」の日本語参考訳です。 はじめに この記事では、インテル® AVX の SIMD (Single Instruction […]
  • インテル® AVX を使用した IIR ガウスぼかしフィルターの実装インテル® AVX を使用した IIR ガウスぼかしフィルターの実装 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「IIR Gaussian Blur Filter Implementation using Intel® Advanced Vector Extensions」の日本語参考訳です。 ソースのダウンロード: gaussian_blur.cpp […]
  • 並列プログラミングにおけるロックの効率的な使用並列プログラミングにおけるロックの効率的な使用 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Using Locks Effectively in Parallel Programming […]