It probably comes as no surprise that streams have an error state. 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 30:
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 or some other serious error |
Note that the flag std::ios_base::goodbit is not represented by any one bit; its value, 0, indicates the absence of any error flag. This means the stream is OK. By convention, all input and output operations have no effect once the stream state is different than 0.
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 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:
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, is considered an attempt to read past the end of the input sequence. Thus, eofbit is set. (Later, we'll see that failbit is set as well.)
If you do not read character-wise, but extract an integer or a string, for example, you 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. Consequently, if the input contains the sequence ... 912749<eof> and an integer is extracted, the eofbit flag (but not failbit) is set.
The flag std::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 of an integer fails, and the failbit is set. Let's see whether failbit would be set in the previous examples:
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.
In this case, the result 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 is indeed read. In this situation only the eofbit is 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 30.2.2).
The flag std::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 0 for other reasons (such as being provided from outside the stream), or the stream cannot allocate memory for its own internal data, as with std::ios_base::iword() and std::ios_base::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.
You can actively check the stream state after each input or output operation.
We explore these possibilities in the next two sections.