以下程序演示了 libc++ 和 libstdc++ 之间的 std::getline 行为不一致(使用 clang3.3)。
程序打开文件 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)