Can a stringstream throw an exception when reading a primitive?

12,630

Solution 1

Summarizing a few answers

By default, streams don't throw exceptions. They can if they are enabled.

stringstream out;
out.exceptions(std::ios::failbit);   // throw exception if failbit gets set

According to the Apache C++ Standard Library User's Guide

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.

So it seems like the safest way to do this would be

string do_something(int in)
{
    stringstream out; // This could throw a bad_alloc
    out << std::fixed << in; // This could set bad or fail bits

    if(out.good())
    {
        return out.str();
    }
    else
    {
        return "";
    }
}

This is overkill though because according to Handling bad_alloc if creating the stream fails, there are bigger problems to worry about, and the program is probably going to exit. So assuming it gets past creating the stream, it's possible but extremely unlikely that the badbit gets set. (Stream gets allocated with memory < sizeof(int)).

It's also unlikely that the failbit gets set (not sure of a use case for reading off the stack other than a corrupt stack). So the following code is sufficient, as recovering from a stream error at this point is unlikley.

string do_something(int in)
{
    stringstream out;
    out << std::fixed << in;
    return out.str();
}

Solution 2

All streams, including istringstreams, can throw exceptions (controllable with ios::exceptions) on reading, eg. when they run out of input. Plus they can throw when running out of memory (eg. when constructing the string currently read).

Your code example, however, performs writing(?) AFAIK writing and int should not produce any exceptions, apart from the obvious out of memory errors (which your code doesn't handle very well).

Share:
12,630
LeviX
Author by

LeviX

Updated on July 19, 2022

Comments

  • LeviX
    LeviX over 1 year

    Looking at some old code we have lots of things like the following:

    // This is dumb
    string do_something(int in)
    {
        stringstream out;
        try
        {
            out << std::fixed << in;
        }
        catch(std::exception &e)
        {
            out << e.what();
        }
    
        return out.str();
    }
    
    // Can't we just do this? Can this ever fail?
    string do_something_better(int in)
    {
        stringstream out;
        out << std::fixed << in;
        return out.str();
    }
    

    When a stringstream reads a primitive can it ever throw an exception? What about when reading a string?