Topic: Error in the standard with fail/eof
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/20 Raw View
clamage@eng.sun.com (Steve Clamage) writes:
>"Michel Michaud" <micm19@gest-netware.cstjean.qc.ca> writes:
>>Everyone knows this classic idiom when reading thru
>>a file :
>>while (fic >> var)
>> ...
>>Well, this is a very potential infinite loop if
>>the standard is correct. Here is why: if a stream
>>is not in the good() state, every i/o operation
>>results in a null operation (the standard says
>>that if you understand the sentry class, and
>>every major author says that too including
>>Stroustrup, so this is clearly true...).
>You are missing something. The result of converting a stream
>"fic" to bool is not fic.good(), but !fic.bad(). In particular,
>if EOF is set, the stream is not good, but is not necessarily
>bad either. Setting the EOF bit does not itself cause bad() to
>become true.
>I believe that answers your remaining questions.
Oops. I meant to say "fail()" everywhere I said "bad()".
The expression "fic>>var" returns a reference to fic. A stream
object can be converted to a boolean via the "operator void*"
member function, which returns "!fail()".
Stream classes also have an "operator!()" member function,
which returns "fail()".
The fail() member function does not check the EOF bit, but
returns true if either the fail bit or the bad bit is set.
The good() member function does check the EOF bit.
Reaching EOF does not necessarily set the fail bit, so if EOF
is set, both good() and fail() can return "false".
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: hinnant@_anti-spam_metrowerks.com (Howard Hinnant)
Date: 1999/04/20 Raw View
In article <7fibq8$epg$1@engnews1.eng.sun.com>, clamage@eng.sun.com (Steve
Clamage) wrote:
> clamage@eng.sun.com (Steve Clamage) writes:
>
> >"Michel Michaud" <micm19@gest-netware.cstjean.qc.ca> writes:
>
> >>Everyone knows this classic idiom when reading thru
> >>a file :
>
> >>while (fic >> var)
> >> ...
>
> >>Well, this is a very potential infinite loop if
> >>the standard is correct. Here is why: if a stream
> >>is not in the good() state, every i/o operation
> >>results in a null operation (the standard says
> >>that if you understand the sentry class, and
> >>every major author says that too including
> >>Stroustrup, so this is clearly true...).
>
> >You are missing something. The result of converting a stream
> >"fic" to bool is not fic.good(), but !fic.bad(). In particular,
> >if EOF is set, the stream is not good, but is not necessarily
> >bad either. Setting the EOF bit does not itself cause bad() to
> >become true.
>
> >I believe that answers your remaining questions.
>
> Reaching EOF does not necessarily set the fail bit, so if EOF
> is set, both good() and fail() can return "false".
I may be mistaken, but I think that this was Michel's point. That is:
while (fic >> var) // while !fail()
...
Assume eofbit is set before the extraction. If fic >> var does nothing
when eofbit is set, then fail() never becomes true. So the question can
be reworded: If eofbit is set prior to an extraction, will the failed
extraction set failbit? If not, then there is potential for the infinite
loop.
-Howard
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/21 Raw View
hinnant@_anti-spam_metrowerks.com (Howard Hinnant) writes:
>In article <7fibq8$epg$1@engnews1.eng.sun.com>, clamage@eng.sun.com (Steve
>Clamage) wrote:
>> clamage@eng.sun.com (Steve Clamage) writes:
>>
>> >"Michel Michaud" <micm19@gest-netware.cstjean.qc.ca> writes:
>>
>> >>Everyone knows this classic idiom when reading thru
>> >>a file :
>>
>> >>while (fic >> var)
>> >> ...
>>
>> >>Well, this is a very potential infinite loop if
>> >>the standard is correct. Here is why: if a stream
>> >>is not in the good() state, every i/o operation
>> >>results in a null operation (the standard says
>> >>that if you understand the sentry class, and
>> >>every major author says that too including
>> >>Stroustrup, so this is clearly true...).
I'm editing my comments in the next paragraph to fix the
error I documented earlier.
>> >You are missing something. The result of converting a stream
>> >"fic" to bool is not fic.good(), but !fic.fail(). In particular,
>> >if EOF is set, the stream is not good, but is not necessarily
>> >failed either. Setting the EOF bit does not itself cause fail() to
>> >become true.
>>
>> >I believe that answers your remaining questions.
>>
>> Reaching EOF does not necessarily set the fail bit, so if EOF
>> is set, both good() and fail() can return "false".
>I may be mistaken, but I think that this was Michel's point. That is:
>while (fic >> var) // while !fail()
> ...
>Assume eofbit is set before the extraction. If fic >> var does nothing
>when eofbit is set, ...
But it does do something: it sets the fail bit. After attempting
the input, fail() is true, and the loop exits.
There seems to be some confusion about eof and fail.
If eof() returns true, it means that no more input is available.
It does not prevent stream operations from being attempted.
For example, you could position the stream to an earlier point,
or push back a character. Either of those operations (if they
succeed) will reset the eof bit. If you attempt an input when eof
is set, the fail bit gets set.
If fail() returns false, it means the previous operation succeeded.
If fail() returns true, it means the previous operation did not
succeed, and that further input, output, and positioning operations
will be ignored until the fail and bad bits are cleared.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/04/21 Raw View
In article <7firm7$dpp$1@engnews1.eng.sun.com>,
clamage@eng.sun.com (Steve Clamage) wrote:
> >I may be mistaken, but I think that this was Michel's point.
It was. His posting is the result of a discussion in fr.comp.lang.c++.
> That is:
>
> >while (fic >> var) // while !fail()
> > ...
>
> >Assume eofbit is set before the extraction. If fic >> var does nothing
> >when eofbit is set, ...
>
> But it does do something: it sets the fail bit.
That's what all of the existing implementations I know of do, and I'm
pretty sure that that is the intent of the standard. However, in the
specification of the constructor of istream::sentry: "If is.good() is
true, prepares for formatted or unformatted input [...]". Then, at the
end of the constructor: "If, after any preparation is completed,
is.good() is true, ok_ != false otherwise, ok_ == false." Conclusion:
if is.good() is false, ok_ is set to false, and *nothing* else is
done. In pseudo-code:
istream::sentry::sentry( istream& source )
{
if ( source.good() )
{
// Prepare for formatted or unformatted input...
}
ok_ = source.good() ;
}
In no case, if source.good() is false, is the failbit in source set. If
the eofbit is set, then ok_ is false, and *nothing* else is done.
The conversion of sentry to bool simply returns ok_.
Now, from 27.6.1.2.1 (common requirements of formatted input):
Each formatted input function begins execution by constructing an
object of class sentry with the noskipws (second) argument false. If
the sentry object returns true, when converted to a value of type
bool, the function endeavors to obtain the requested input.
Again, an if without an else. But if eofbit is set, the sentry object
evaluates false, and *nothing* else is done. Or at least, the standard
doesn't say that anything else is done.
I'm sure that this is not the intent and I'm also sure that no
implementation does this. The idiom is too widely spread for it not to
work with a given implementation. But unless I've missed something in
the standard, it is not what the standard says. What I'm missing, of
course, is the else-clause of either the if in istream::sentry::sentry,
or in the formatted input. But I've read the entire text of
istream::sentry::sentry, and it's not there. And if I understand the
quoted paragraph of 27.6.1.2.1, all of the sections which follow explain
what happens when "the function endeavors to obtain the requested
input." Which is in the then branch of the if, and thus, not executed
in this case.
> After attempting
> the input, fail() is true, and the loop exits.
See above. If eofbit is set, operator>> never attempts input, but
returns without doing anything.
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86 27
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/20 Raw View
"Michel Michaud" <micm19@gest-netware.cstjean.qc.ca> writes:
>Everyone knows this classic idiom when reading thru
>a file :
>while (fic >> var)
> ...
>Well, this is a very potential infinite loop if
>the standard is correct. Here is why: if a stream
>is not in the good() state, every i/o operation
>results in a null operation (the standard says
>that if you understand the sentry class, and
>every major author says that too including
>Stroustrup, so this is clearly true...).
You are missing something. The result of converting a stream
"fic" to bool is not fic.good(), but !fic.bad(). In particular,
if EOF is set, the stream is not good, but is not necessarily
bad either. Setting the EOF bit does not itself cause bad() to
become true.
I believe that answers your remaining questions.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Michel Michaud" <micm19@gest-netware.cstjean.qc.ca>
Date: 1999/04/19 Raw View
Everyone knows this classic idiom when reading thru
a file :
while (fic >> var)
...
Well, this is a very potential infinite loop if
the standard is correct. Here is why: if a stream
is not in the good() state, every i/o operation
results in a null operation (the standard says
that if you understand the sentry class, and
every major author says that too including
Stroustrup, so this is clearly true...).
But the last successful read in the file CAN
also set the eofbit, without the failbit. Mr.
Clamage confirmed this in a recent posting and
the standard can be interpreted that way. It is
not always what will happen (the eof could be
set by the next, unsuccessful, read with the
fail) but it is possible by the standard and
it happens with some compilers.
The problem is: if eof is true but not fail,
the loop won't finish because the test is on
fail (if (fic) == if (!fic.fail())) and this
flag will not be set because it's a null
operation.
I am not sure how this is supposed to be. Maybe
the failbit should be set when trying to read
with eof set, but the standard clearly states
otherwise. With the standard as it is, I don't
see how one is supposed to read a file and
check states. And more importantly, every book
using the while (fic >> var) technique must
use a non conforming compiler if it is to
work for sure !
I would like the answer to be: eof is only set
by a failed read, not after a successful one.
This, in a way, is what I understood from the
standard. But if a quasi-mythical figure says
otherwise (Clamage :-]) I suppose he knows
better and he just broke many programs !
Michel Michaud micm19@removethis.mail2.cstjean.qc.ca
http://www3.sympatico.ca/michel.michaud
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]