3

I'm using Mac OSX 10.8.1 (Mountain Lion) with: Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn) - latest available.

Clang with libc++ std::istream::peek() seems to work incorrectly regarding eof detection. Problem does not appear with libstdc++.

Simple example below is giving different results depending on std library version:

test.cpp:

#include <iostream>
#include <sstream>

void printstat(std::istream& data) {
  std::cout << "flags:  eof: " << data.eof() << ";  good: " << data.good() << ";  bad: " << data.bad() << "  fail: " << data.fail() << std::endl;
}

int main() {
  std::stringstream data("a"); 
  printstat(data);

  while (data.good()) {
    char a = data.get();
    std::cout << "get(): " << a << std::endl;
    printstat(data);

    data.peek();
    std::cout << "peek()" << std::endl;
    printstat(data);
    std::cout << std::endl;
  }

  return 0;
}

Output from file compiled with "clang++ -stdlib=libstdc++ test.cpp" (this looks correct):

flags:  eof: 0;  good: 1;  bad: 0  fail: 0
get(): a
flags:  eof: 0;  good: 1;  bad: 0  fail: 0
peek()
flags:  eof: 1;  good: 0;  bad: 0  fail: 0

Output from file compiled with "clang++ -stdlib=libc++ test.cpp" (this looks incorrect for me):

get(): a
flags:  eof: 0;  good: 1;  bad: 0  fail: 0
peek()
flags:  eof: 0;  good: 1;  bad: 0  fail: 0

get(): ?
flags:  eof: 1;  good: 0;  bad: 0  fail: 1
peek()
flags:  eof: 1;  good: 0;  bad: 0  fail: 1

Simplest workaround for this problem seems to be using libstdc++ instead of libc++. Unfortunately I need to use some c++11 features so libc++ is the only solution.

I found some posts there, which are reporting discrepancy between libc++ and libstdc++ in eof bit behaviour but not same as mine.

Did anyone encounter same problem as mine. Is there any common solution to solve it? I can imagine some dirty workarounds for it but I would rather not to use it.

Thank you in advance for help

gringo001
  • 31
  • 3

1 Answers1

1

My apologies. This is a bug in libc++. It has been fixed in the libc++ svn public trunk, but the fix requires a recompiled libc++.dylib, which understandably is not present on OS X 10.8.y.

The llvm svn server is down at the moment but I believe the fix was to simply check for eof in basic_istream<_CharT, _Traits>::peek():

+            if (traits_type::eq_int_type(__r, traits_type::eof()))
+                this->setstate(ios_base::eofbit);

The workarounds, as you have already surmised, is to not depend upon an accurate eof check after peek.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577