Skip to content

<ostream>: Exception from streambuf should be caught and not rethrown #4322

@StephanTLavavej

Description

@StephanTLavavej

Originally reported as DevCom-10555755 / VSO-1939195 / AB#1939195 . I've cleaned up the repro and especially the Standardese citations, so I believe this is a bug.

D:\GitHub\STL\out\x64>type meow.cpp
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;

class MyStreamBuf : public streambuf {
protected:
    // N4971 [streambuf.virt.get]/1-2:
    // "streamsize showmanyc();
    // Returns: An estimate of the number of characters available in the sequence, or -1.
    // If it returns a positive value, then successive calls to underflow() will not return
    // traits::eof() until at least that number of characters have been extracted from the stream.
    // If showmanyc() returns -1, then calls to underflow() or uflow() will fail. [Note 277]
    // Default behavior: Returns zero."

    // Note 277:
    // "underflow or uflow can fail by throwing an exception prematurely. The intention
    // is not only that the calls will not return eof() but that they will return "immediately"."

    int_type underflow() override {
        throw runtime_error("WOOF");
    }
};

int main() {
    MyStreamBuf rdbuf;
    ostringstream oss;
    assert(oss.exceptions() == ios_base::goodbit);

    try {
        // N4971 [ostream.inserters]/8-9:
        // "basic_ostream& operator<<(basic_streambuf<charT, traits>* sb);
        // Gets characters from sb and inserts them in *this. Characters are
        // read from sb and inserted until any of the following occurs:
        // [...]
        // - an exception occurs while getting a character from sb.
        // If the function inserts no characters, it calls setstate(failbit) (which
        // may throw ios_base::failure ([iostate.flags])). If an exception was thrown
        // while extracting a character, the function sets failbit in the error state,
        // and if failbit is set in exceptions() the caught exception is rethrown."
        oss << &rdbuf;
        cout << "No exception observed in main().\n";
    } catch (const runtime_error&) {
        cout << "Caught runtime_error in main().\n";
    }

    assert(oss.rdstate() == ios_base::failbit);
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /MTd /Od meow.cpp && meow
meow.cpp
Caught runtime_error in main().

libstdc++ and libc++ print "No exception observed in main()." as shown by https://godbolt.org/z/Yq3noKn8s .

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions