file stream tellg/tellp and gcc-4.6 is this a bug?
This code:
#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
int main()
{
std::remove("test.txt");
std::fstream f("test.txt",std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc);
std::cout << f.good() << std::endl;
f<<"test"<< std::flush;
std::cout << f.tellg() << " " << f.tellp() << std::endl;
f.seekg(0);
std::string s;
f>>s;
std::cout << f.tellg() << " " << f.tellp() << std::endl;
}
Gives following output in gcc-4.4.5
1
4 4
4 4
i.e. both tellg and tellp returned expected stream position 4.
While gcc-4.6.0
Gives:
1
4 4
-1 4
Where can I find a reference to tell:
- 1st case is correct (bug in gcc-4.6)
- 2nd case is correct (bug in gcc < gcc-4.6)
- Bo开发者_如何学JAVAth case are correct the behavior is undefined
Ok, it is not a bug, even it seems that it is required behavior:
According to C++ 2003 standard:
tellg(): (27.6.1.3)
After constructing a sentry object, if fail() != false, returns pos_type(-1) to indicate failure. Otherwise, returns rdbuf()->pubseekoff(0, cur, in).
sentry (27.6.1.1.2):
if noskipws is zero and is.flags() & ios_base::skipws is nonzero, the func- tion extracts and discards each character as long as the next available input character c is a whitespace character. If is.rdbuf()->sbumpc() or is.rdbuf()->sgetc() returns traits::eof(), the function calls setstate(failbit | eofbit) (which may throw ios_base::failure).
So basically
- tellg() creates sentry object:
- sentry extracts white space characters and should set failbit after getting to eof.
- tellg() sees failbit should return eof() (-1)
So gcc-4.6 seems to behave correctly...
I can confirm the difference. However, it is not a difference of the compiler, it is not a difference of the standard library headers, it is a difference of the linked shared library.
It doesn't depend on the gcc version. It doesn't depend on architecture:
t44: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
t45: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
t46: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
The real difference seems to be
- meerkat: libstdc++6 4.5.1-7ubuntu2
- natty: libstdc++6 4.6.0-3~ppa1 (from here)
On ubuntu meerkat
$ uname -a
Linux natty 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 i686 GNU/Linux
$ for a in t4?; do ./$a; done
1
4 4
4 4
1
4 4
4 4
1
4 4
4 4
On ubuntu natty
Linux natty 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
sehe@natty:/mnt/jail/home/sehe$ for a in t4?; do ./$a; done
1
4 4
-1 4
1
4 4
-1 4
1
4 4
-1 4
Ok, separate from the version analysis, which I'll leave for good measure, here is the answer:
PR/26211
I'll try to find source, but this thread discusses whether the documentation needs to be updated due to this change. It is therefore, a documented change :)
Edit Only found this: libstdc++/26211 (again) + N3168
From this page: http://gcc.gnu.org/ml/libstdc++/2011-04/msg00026.html
Hey, all.
I recently started using gcc-4.6.0 and it seems that the behaviour of std::istream::tellg() has changed when (just) the eofbit is set. I managed to track this down to PR/26211, and I'm not debating the changes.
It took me a while to figure out what was wrong because the doxygen for tellg() says:
If fail() is not false, returns pos_type(-1) to indicate failure. Otherwise returns rdbuf()->pubseekoff(0,cur,in).
That's almost word for word what Langer and Kreft says, so I'm presuming DR60's change to 27.6.1.3 paragraph 37 has lead to this change in libstdc++ behaviour.
Should the libstdc++ doxygen be updated to say something about the fact that calling
tellg()
wheneof()
will also returnpos_type(-1)
(because of the fact that it constructs a sentry)? Are there other functions that also should have updated documentation as a result of DR60?
精彩评论