次のプログラムは、libc++ と libstdc++ (clang3.3 を使用) の間で std::getline の動作に矛盾があることを示しています。
プログラムはファイル testfile を開き、eof まで読み取り、次に ifstream::clear を使用してエラー ビットをクリアし、同じファイルハンドルから再度読み取りを試みて、新しいデータがファイルに追加されたかどうかを確認します。
#include <fstream>
#include <iostream>
#include <unistd.h>
using namespace std;
int main() {
ifstream* file = new ifstream("testfile");
if ( ! file->is_open() ) {
cout << "testfile does not exist" << endl;
return -1;
}
while ( 1 ) {
file->clear(); // remove end of file evil bits
string line;
// workaround:
// file->seekg(file->tellg());
while ( getline(*file, line) )
cout << "read line: " << line << endl;
if ( file->eof() )
cout << "File reports eof after getline\n";
usleep(1000000);
}
}
libstdc++ を使用して (コンパイラに関係なく)、プログラムの実行中にデータを testfile に追加すると、データは次のループ反復で getline 呼び出しによって読み取られます。
libc++ を使用する OS-X 上の clang 3.3 では、最初にファイルの終わりが検出された後、getline は常に失敗し、ファイルに追加されたデータを読み取ることなく、後続のすべての呼び出しで eof ビットを設定します。現在の位置をシークするだけの回避策のコメントを外すと、libstdc++ の動作が復元されます。clang++ -stdlib=libstdc++ を使用して libstdc++ に対してコンパイルすると、以前の動作に戻ります。
これが予想される変更であるかどうかは誰にもわかりますか? サポートされていない方法でこれを行おうとしていますか、それとも現在の libc++ バージョンの問題ですか?
私にとってこの動作をトリガーする clang バージョンは、XCode for Mavericks に同梱されている最新のものです。
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
リンクされている libc++ ライブラリには、次のバージョン情報があります。
/usr/lib/libc++.1.dylib:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libc++abi.dylib (compatibility version 1.0.0, current version 48.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)