Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   std::istream::tellg vs eofbit flag (http://www.velocityreviews.com/forums/t963024-std-istream-tellg-vs-eofbit-flag.html)

mathieu 07-25-2013 04:41 PM

std::istream::tellg vs eofbit flag
 
Hi,

I'd like to check if my understanding of the standard is correct. Is the following program supposed to work ?

$ cat file.cxx
#include <cassert>
#include <fstream>
#include <sstream>

int main ()
{
std::ifstream ifs (__FILE__, std::ios::binary);
std::stringstream ss;

assert (0 == ifs.tellg ());

ifs >> ss.rdbuf ();

assert (ifs.eofbit == ifs.rdstate ());
assert (ifs.eof());
assert (-1 != ifs.tellg ()); // works with g++ 4.4

return 0;
}

I am getting different results using either g++ 4.4 or g++ 4.7.

Thanks.

Victor Bazarov 07-25-2013 05:05 PM

Re: std::istream::tellg vs eofbit flag
 
On 7/25/2013 12:41 PM, mathieu wrote:
> I'd like to check if my understanding of the standard is correct. Is the following program supposed to work ?
>
> $ cat file.cxx
> #include <cassert>
> #include <fstream>
> #include <sstream>
>
> int main ()
> {
> std::ifstream ifs (__FILE__, std::ios::binary);


The macro __FILE__ does not necessarily expand into a valid file name in
the environment where the resulting binary is going to run, you realize
that, yes?

> std::stringstream ss;
>
> assert (0 == ifs.tellg ());
>
> ifs >> ss.rdbuf ();
>
> assert (ifs.eofbit == ifs.rdstate ());
> assert (ifs.eof());
> assert (-1 != ifs.tellg ()); // works with g++ 4.4
>
> return 0;
> }
>
> I am getting different results using either g++ 4.4 or g++ 4.7.


Different in what way?

'tellg' returns pos_type(-1) to indicate *failure*. Are you sure
reading out the entire file is supposed to set the failbit? If you try
*reading* after the 'eof' condition has been achieved, *then* you get a
failure (because that input operation fails), and *then* 'tellg' should
return pos_type(-1). That's my take on it.

V
--
I do not respond to top-posted replies, please don't ask

mathieu 07-26-2013 06:37 AM

Re: std::istream::tellg vs eofbit flag
 
On Thursday, July 25, 2013 7:05:00 PM UTC+2, Victor Bazarov wrote:
> On 7/25/2013 12:41 PM, mathieu wrote:
>
> > I'd like to check if my understanding of the standard is correct. Is the following program supposed to work ?

>
> >

>
> > $ cat file.cxx

>
> > #include <cassert>

>
> > #include <fstream>

>
> > #include <sstream>

>
> >

>
> > int main ()

>
> > {

>
> > std::ifstream ifs (__FILE__, std::ios::binary);

>
>
>
> The macro __FILE__ does not necessarily expand into a valid file name in
>
> the environment where the resulting binary is going to run, you realize
>
> that, yes?
>
>
>
> > std::stringstream ss;

>
> >

>
> > assert (0 == ifs.tellg ());

>
> >

>
> > ifs >> ss.rdbuf ();

>
> >

>
> > assert (ifs.eofbit == ifs.rdstate ());

>
> > assert (ifs.eof());

>
> > assert (-1 != ifs.tellg ()); // works with g++ 4.4

>
> >

>
> > return 0;

>
> > }

>
> >

>
> > I am getting different results using either g++ 4.4 or g++ 4.7.

>
>
>
> Different in what way?
>
>
>
> 'tellg' returns pos_type(-1) to indicate *failure*. Are you sure
>
> reading out the entire file is supposed to set the failbit? If you try
>
> *reading* after the 'eof' condition has been achieved, *then* you get a
>
> failure (because that input operation fails), and *then* 'tellg' should
>
> return pos_type(-1). That's my take on it.


Not according to cplusplus.com:

http://www.cplusplus.com/reference/i...istream/tellg/

"Notice that the function will work even if the eofbit flag is set before the call."

Hence, my question...

Victor Bazarov 07-26-2013 01:01 PM

Re: std::istream::tellg vs eofbit flag
 
On 7/26/2013 2:37 AM, mathieu wrote:
> On Thursday, July 25, 2013 7:05:00 PM UTC+2, Victor Bazarov wrote:
>> On 7/25/2013 12:41 PM, mathieu wrote:
>>
>>> I'd like to check if my understanding of the standard is correct. Is the following program supposed to work ?

>>
>>>

>>
>>> $ cat file.cxx

>>
>>> #include <cassert>

>>
>>> #include <fstream>

>>
>>> #include <sstream>

>>
>>>

>>
>>> int main ()

>>
>>> {

>>
>>> std::ifstream ifs (__FILE__, std::ios::binary);

>>
>>
>>
>> The macro __FILE__ does not necessarily expand into a valid file name in
>>
>> the environment where the resulting binary is going to run, you realize
>>
>> that, yes?
>>
>>
>>
>>> std::stringstream ss;

>>
>>>

>>
>>> assert (0 == ifs.tellg ());

>>
>>>

>>
>>> ifs >> ss.rdbuf ();

>>
>>>

>>
>>> assert (ifs.eofbit == ifs.rdstate ());

>>
>>> assert (ifs.eof());

>>
>>> assert (-1 != ifs.tellg ()); // works with g++ 4.4

>>
>>>

>>
>>> return 0;

>>
>>> }

>>
>>>

>>
>>> I am getting different results using either g++ 4.4 or g++ 4.7.

>>
>>
>>
>> Different in what way?


....and you didn't answer this question.

>>
>>
>>
>> 'tellg' returns pos_type(-1) to indicate *failure*. Are you sure
>>
>> reading out the entire file is supposed to set the failbit? If you try
>>
>> *reading* after the 'eof' condition has been achieved, *then* you get a
>>
>> failure (because that input operation fails), and *then* 'tellg' should
>>
>> return pos_type(-1). That's my take on it.

>
> Not according to cplusplus.com:


What is the meaning of "not" in your statement here? Somehow
cplusplus.com has something to say about /my take on/ how tellg
operates? Or is there something in its explanation that contradicts
what I wrote on how tellg works (or supposed to, anyway)?

>
> http://www.cplusplus.com/reference/i...istream/tellg/
>
> "Notice that the function will work even if the eofbit flag is set before the call."


Yes. Do you realize that 'eofbit' and 'badbit' are not the same? When
we say "failure", it means the 'badbit' is set. 'eofbit' is only set
when the reading *reaches* the end of the stream.

>
> Hence, my question...


So, to answer your question, yes, the program is supposed to work. If
it does not (it would be nice to see your explanation of what "does not"
is here), then it is likely due to a bug in the implementation of the
standard I/O library that you're using. <shrug>

The function 'tellg' is supposed to return rdbuf()->pubseekoff(0, cur,
in), if the failbit is *not* set (i.e. fail() == false). If the failbit
*is* set (indicating the failure of the last operation) *then* it
returns -1.

Instead of asserting on 'tellg', see if you get the 'fail()' to return
'false' in that case (isn't that what you suppose should hold in your
situation?) and then we could start trying to understand what *exactly*
is going wrong in one of your programs.

V
--
I do not respond to top-posted replies, please don't ask

James Kanze 07-28-2013 06:54 PM

Re: std::istream::tellg vs eofbit flag
 
On Friday, July 26, 2013 2:01:14 PM UTC+1, Victor Bazarov wrote:
> On 7/26/2013 2:37 AM, mathieu wrote:


> > On Thursday, July 25, 2013 7:05:00 PM UTC+2, Victor Bazarov wrote:
> >> On 7/25/2013 12:41 PM, mathieu wrote:
> >>> I'd like to check if my understanding of the standard is correct. Is the following program supposed to work ?
> >>> $ cat file.cxx
> >>> #include <cassert>
> >>> #include <fstream>
> >>> #include <sstream>


> >>> int main ()
> >>> {
> >>> std::ifstream ifs (__FILE__, std::ios::binary);


> >> The macro __FILE__ does not necessarily expand into a valid file name in
> >> the environment where the resulting binary is going to run, you realize
> >> that, yes?


> >>> std::stringstream ss;
> >>> assert (0 == ifs.tellg ());
> >>> ifs >> ss.rdbuf ();
> >>> assert (ifs.eofbit == ifs.rdstate ());
> >>> assert (ifs.eof());


I'm not sure that the two asserts above are guaranteed to pass
(although it's hard to imagine an implementation where they
didn't).

> >>> assert (-1 != ifs.tellg ()); // works with g++ 4.4
> >>> return 0;
> >>> }


> >>> I am getting different results using either g++ 4.4 or g++ 4.7.


The requirements have changed between C++03 and C++11. C++03
requires std::istream::seekg to fail if eofbit is set. C++11
says that eofbit will first be reset, before attempting the
seek. (I believe that the behavior specified by C++11 was what
was wanted from the beginning, but C++03 definitly says that
seekg should fail if eofbit is set.)

[...]
> > http://www.cplusplus.com/reference/i...istream/tellg/


> > "Notice that the function will work even if the eofbit flag
> > is set before the call."


Only in C++11. The language has changed in this regard.

> Yes. Do you realize that 'eofbit' and 'badbit' are not the same? When
> we say "failure", it means the 'badbit' is set.


No. When we say "failure", we mean that either 'failbit' or
'badbit' are set. Most implementations of istream will never
set 'badbit'. (They should, in case there is a real hardware
read error, but they don't.)

> 'eofbit' is only set
> when the reading *reaches* the end of the stream.


More correctly, 'eofbit' is only set when the standard says it
should be set. In general, I would expect it to be set whenever
streambuf::sgetc, streambuf::sbumpc or streambuf::snextc returns
end of file. But the standard is fairly vague about this; it
doesn't mention setting eofbit in the description of operator>>
to a streambuf. One could argue that this means that eofbit
shouldn't be set. (One could also argue that this is an
oversight. C++03 also says that this >> behaves as a formatted
input function, which means that it should skip leading
whitespace. It didn't in classical iostreams, and this has been
corrected in C++11. Perhaps not setting eofbit is a similar
oversight, which just hasn't been corrected yet.)

> > Hence, my question...


> So, to answer your question, yes, the program is supposed to work. If
> it does not (it would be nice to see your explanation of what "does not"
> is here), then it is likely due to a bug in the implementation of the
> standard I/O library that you're using. <shrug>


His program is based on unspecified behavior at one point, and
behavior which has changed between C++03 and C++11 at another.
My guess is that g++ 4.4 is implementing exactly what is
specified in C++03, and that g++ 4.7 is implementing the C++11
behavior, considering the change as a "correction", and so not
requiring -std=c++11 to get it.

--
James


All times are GMT. The time now is 09:29 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.