Skip to content. Skip to navigation

ICTP Portal

Sections
You are here: Home Manuals on-line PGI Compiler pgC_lib stdlibug 2.4 Error State of Streams
Personal tools
Document Actions

2.4 Error State of Streams



Click on the banner to return to the user guide home page.

2.4 Error State of Streams

It probably comes as no surprise that streams have an error state. Our examples have avoided it to this point, so we'll deal with it now. When an error occurs, flags are set in the state according to the general category of the error. Flags and their error categories are summarized in Table 5 below:

iostate flag
Error category
ios_base::goodbit
Everything's fine
ios_base::eofbit
An input operation reached the end of an input sequence
ios_base::failbit
An input operation failed to read the expected character, or
An output operation failed to generate the desired characters
ios_base::badbit
Indicates the loss of integrity of the underlying input or output sequence

Note that the flag ios_base::goodbit is not really a flag; its value, zero, indicates the absence of any error flag. It means the stream is OK. By convention, all input and output operations have no effect once the stream state is different than zero.

There are several situations when both eofbit and failbit are set; however, the two have different meanings and do not always occur in conjunction. The flag ios_base::eofbit is set when there is an attempt to read past the end of an input sequence. This occurs in the following two typical examples:

  1. Assume the extraction happens character-wise. Once the last character is read, the stream is still in good state; eofbit is not yet set. Any subsequent extraction, however, will be considered an attempt to read past the end of the input sequence. Thus, eofbit will be set.

  2. If you do not read character-wise, but extract an integer or a string, for example, you will always read past the end of the input sequence. This is because the input operators read characters until they find a separator, or hit the end of the input sequence. If the input contains the sequence ... 912749<eof> and an integer is extracted, eofbit will be set.

The flag ios_base::failbit is set as the result of a read or write operation that fails. For example, if you try to extract an integer from an input sequence containing only white spaces, the extraction fails, and the failbit is set. Let's see whether failbit would be set in the previous examples:

  1. After reading the last available character, the extraction not only reads past the end of the input sequence; it also fails to extract the requested character. Hence, failbit is set in addition to eofbit.

  2. Here it is different. Although the end of the input sequence is reached by extracting the integer, the input operation does not fail and the desired integer will indeed be read. Hence, in this situation only the eofbit will be set.

In addition to these input and output operations, there are other situations that can trigger failure. For example, file streams set failbit if the associated file cannot be opened (see Section 2.5).

The flag ios_base::badbit indicates problems with the underlying stream buffer. These problems could be:

  • Memory shortage. There is no memory available to create the buffer, or the buffer has size zero for other reasons[21], or the stream cannot allocate memory for its own internal data, as with iword and pword.

  • The underlying stream buffer throws an exception. The stream buffer might lose its integrity, as in memory shortage, or code conversion failure, or an unrecoverable read error from the external device. The stream buffer can indicate this loss of integrity by throwing an exception, which is caught by the stream and results in setting the badbit in the stream's state.

Generally, you should keep in mind that badbit indicates an error situation that is likely to be unrecoverable, whereas failbit indicates a situation that might allow you to retry the failed operation. The flag eofbit simply indicates the end of the input sequence.

What can you do to check for such errors? You have two possibilities for detecting stream errors:

  • You can declare that you want to have an exception raised once an error occurs in any input or output operation, or

  • You can actively check the stream state after each input or output operation.

We will explore these possibilities in the next two sections.

2.4.1 Checking the Stream State

Let's first examine how you can check for errors using the stream state. A stream has several member functions for this purpose, which are summarized with their effects in the Table 6:

ios_base member function
Effect
bool good()
True if no error flag is set
bool eof()
True if eofbit is set
bool fail()
True if failbit or badbit is set
bool bad()
True if badbit is set
bool operator!()
As fail()
operator void*()
Null pointer if fail() and non-null value otherwise
iostate rdstate()
Value of stream state

It is a good idea to check the stream state in some central place, for example:

if (!cout) error();

The state of cout is examined with operator!(), which will return true if the stream state indicates an error has occurred.

An ostream can also appear in a boolean position to be tested as follows:

if (cout << x) // okay!

The magic here is the operator void*() that returns a non-zero value when the stream state is non-zero.

Finally, the explicit member functions can also be used:

if (cout << x, cout.good()) // okay!;

Note that there is a difference between good() and operator!(). The function good() takes all flags into account; operator!() and fail() ignore eofbit.

2.4.2 Catching Exceptions

By default a stream does not throw any exceptions.[23] You have to explicitly activate an exception because a stream contains an exception mask. Each flag in this mask corresponds to one of the error flags. For example, once the badbit flag is set in the exception mask, an exception will be thrown each time the badbit flag gets set in the stream state. The following code demonstrates how to activate an exception on an input stream InStr:

try {
   InStr.exceptions(ios_base::badbit | ios_base::failbit);    \\1
   in >> x;
   // do lots of other stream i/o
}
catch(ios_base::failure& exc)                                 \\2
{   cerr << exc.what() << endl; 
    throw;
}
//1In calling the exceptions() function, you indicate what flags in the stream's state shall cause an exception to be thrown.[24]
//2Objects thrown by the stream's operations are of types derived from ios_base::failure. Hence this catch clause will catch all stream exceptions in principle. We qualify this generalization because a stream might fail to catch certain exceptions, e.g., bad_alloc, so that exceptions other than ios_base::failure might be raised. That's how exception handling in C+ works: you never know what exceptions will be raised.

Generally, it is a good idea to activate the badbit exception and suppress the eofbit and failbit exceptions, because the latter do not represent exceptional states. A badbit situation, however, is likely to be a serious error condition similar to the memory shortage indicated by a bad_alloc exception. Unless you want to suppress exceptions thrown by iostreams altogether, we would recommend that you switch on the badbit exception and turn off eofbit and failbit.


©Copyright 1996, Rogue Wave Software, Inc.


Powered by Plone This site conforms to the following standards: