cin seekg/tellg 在 OS X 与 Linux 上的不同行为

Different behavior of cin seekg/tellg on OS X vs Linux

提问人:Alex Reinking 提问时间:2/27/2015 最后编辑:Alex Reinking 更新时间:2/27/2015 访问量:503

问:

我正在尝试在我正在编写的程序中读取整个重定向到中,并发现在 OS X 上,seekg 和 tellg 在应用于 .stdinstd::stringcin

这是我的最小示例:

#include <iostream>
using namespace std;

int main()
{
    cin.clear();
    cin.seekg(0, ios::end);
    if (cin.fail() || cin.bad())
        cout << "Cin seek failed." << endl;
    cout << cin.tellg() << endl;
    return 0;
}

在 Linux 上,当我将这个程序应用于它自己的源代码时,我得到:

alex@linux:~$ g++ size.cpp -o size
alex@linux:~$ ./size < ./size.cpp 
225
alex@linux:~$ wc -c size.cpp
     225 size.cpp

但是,在OS X上,我得到:

alex@osx:~$ g++ size.cpp -o size
alex@osx:~$ ./size < ./size.cpp 
-1
alex@osx:~$ wc -c size.cpp
     225 size.cpp

请注意,不会打印“Cin seek failed.”错误消息。为什么会这样?我做错了什么吗?

更新

这似乎是OS X标准库的问题,尽管这适用于Linux上的clang。它使用 Homebrew G++ 4.9 在 OS X 上运行。

alex@osx:~$ g++-4.9 original.cpp -o original
alex@osx:~$ ./original < big.txt 
254167055
alex@osx:~$ g++ original.cpp -o original
alex@osx:~$ ./original < big.txt 
-1

编辑

下面是一些将文件读入缓冲区的快速代码

#include <iostream>
#include <stdio.h>
using namespace std;

int main(void)
{
    fseek(stdin, 0, SEEK_END);
    int read_size = ftell(stdin);

    char *buf = new char[read_size];
    rewind(stdin);
    read_size = fread(buf, 1, read_size, stdin);

    string str;
    str.append(buf, read_size); // I want to dodge this copy
                                // because speed is important

    delete [] buf;

    cout << str.length() << endl;
}

下面是一些用于将文件读入缓冲区的慢代码

#include <iostream>
using namespace std;

int main(void)
{
    string str((std::istreambuf_iterator<char>(cin)),
                std::istreambuf_iterator<char>());
    cout << str.length() << endl;
}

控制台输出(big.txt 为 250MB 左右):

alex@osx:~$ time ./size < big.txt 
254167055

real    0m0.339s
user    0m0.074s
sys 0m0.264s
alex@osx:~$ time ./size-slow < big.txt 
254167055

real    1m18.180s
user    1m16.212s
sys 0m0.653s
C++ Linux macOS IOSTREAM

评论

0赞 Alex Reinking 2/27/2015
我应该注意,无论我是否在每个系统上使用“clang/gcc”命令,我都会得到相同的结果。
1赞 WhozCraig 2/27/2015
不,我要在这个地方寻找一段时间。它真的让我很感兴趣。我和 Dietmar 在线。这家伙对iostream编程的遗忘比大多数人所知道的还要多。给它时间。专家们从最陌生的地方和时间流出。真的是流浪汉istreambuf_iterator表现不佳。有点震惊,这对你来说太可怜了。至少你可以回退到 C api,所以你在紧要关头得到了它。
1赞 Alex Reinking 2/27/2015
更新:这与OS X的libc++版本有关。使用 libstd++ 使用 G++ 4.9 Homebrew 进行编译就可以了。
1赞 WhozCraig 2/27/2015
我可以确认这一点。我只是将当前目标的 Xcode 中的标准 C++ 库选择切换到 libstdc++,并且(在诅咒失去 wtf 之后!!)它确实可以正常工作。Helluva 找到,伙计。std::unique_ptr<>
1赞 l'L'l 2/27/2015
Apple Bug Reporter — developer.apple.com/bug-reporting

答: 暂无答案