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实现中的一个问题,而不是迭代器.
不幸的是,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,即使修复程序位于标头中.