Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
StephanTLavavej opened this issue Jan 16, 2024 · 0 comments · Fixed by #4372
Closed

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

StephanTLavavej opened this issue Jan 16, 2024 · 0 comments · Fixed by #4372
Labels
bug Something isn't working fixed Something works now, yay!

Comments

@StephanTLavavej
Copy link
Member

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 .

@StephanTLavavej StephanTLavavej added the bug Something isn't working label Jan 16, 2024
@StephanTLavavej StephanTLavavej added the fixed Something works now, yay! label Feb 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed Something works now, yay!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant