如何用libc ++ istream_iterator读取文件中的0xFF?

vis*_*nda 5 c++ istream-iterator libstdc++ libc++

请考虑以下示例代码:

#include <iostream>

using namespace std;

int main()
{
  istreambuf_iterator<char> eos;
  istreambuf_iterator<char> iit(cin.rdbuf());
  int i;
  for (i = 0; iit != eos; ++i, ++iit) {
    cout << *iit;
  }
  cout << endl << i << endl;
}
Run Code Online (Sandbox Code Playgroud)

以及包含以下内容的输入文件:"foo\xffbar":

$ hexdump testin
0000000 66 6f 6f ff 62 61 72
0000007
Run Code Online (Sandbox Code Playgroud)

现在使用clang libc ++ vs gnu libstdc ++进行测试:

$ make test
clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libc++ -o bug-libcc bug.cpp
clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libstdc++ -o bug-libstd bug.cpp
./bug-libcc < testin
foo
3
./bug-libstd < testin
foo?bar
7
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,libc ++版本认为0xff是流的结尾并且它停止读取.所以这导致了几个问题.

1)这是我应该报告的libc ++中的错误吗?我的谷歌搜索现有的错误没有任何结果.

2)有解决这个问题的好方法吗?

编辑

以下代码有效:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
  ifstream ifs ("testin", ios::binary);
  istreambuf_iterator<char> eos;
  istreambuf_iterator<char> iit(ifs.rdbuf());
  int i;
  for (i = 0; iit != eos; ++i, ++iit) {
    cout << *iit;
  }
  cout << endl << i << endl;
}
Run Code Online (Sandbox Code Playgroud)

让我相信它是一个二进制转换问题,但这并不能解释为什么libstdc ++正常工作.

EDIT2

使用没有二进制文件也可以正常工作:

ifstream ifs ("testin");
Run Code Online (Sandbox Code Playgroud)

所以肯定会发生一些可疑的事情.看起来它可能是cin实现中的一个问题,而不是迭代器.

How*_*ant 5

不幸的是,libc ++中仍然存在一个错误(除了指出的一个ecatmur).这是修复:

Index: include/__std_stream
===================================================================
--- include/__std_stream    (revision 176092)
+++ include/__std_stream    (working copy)
@@ -150,7 +150,7 @@
     {
         for (int __i = __nread; __i > 0;)
         {
-            if (ungetc(__extbuf[--__i], __file_) == EOF)
+            if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
                 return traits_type::eof();
         }
     }
Run Code Online (Sandbox Code Playgroud)

我会尽快检查这个.抱歉,这个bug.谢谢你引起我的注意.

修复已提交的修订版176822到libcxx public svn trunk.修复程序需要重新编译的dylib,即使修复程序位于标头中.