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

std::__ios_failure when using fmt/ostream.h #1666

Closed
suo opened this issue May 6, 2020 · 3 comments
Closed

std::__ios_failure when using fmt/ostream.h #1666

suo opened this issue May 6, 2020 · 3 comments

Comments

@suo
Copy link

suo commented May 6, 2020

Hey, in PyTorch we have some very involved code for printing out Tensor values to a stream that seems to fail when we try to use fmt on it. I've extracted a small reproduction of the issue here:

#include <fmt/format.h>
#include <fmt/ostream.h>

struct FormatGuard {
  FormatGuard(std::ostream & out)
  : out(out), saved(nullptr) {
    saved.copyfmt(out);
  }
  ~FormatGuard() {
    out.copyfmt(saved);
  }
private:
  std::ostream & out;
  std::ios saved;
};


struct Foo {
    std::string hello;
};

std::ostream& operator<<(std::ostream& os, const Foo& foo) {
    FormatGuard guard(os);
    os << foo.hello;
    return os;
}

int main() {
    auto f = Foo{"hello"};
    std::cout << f << std::endl;
    fmt::print("{}\n", f);
    return 0;
}

Compiling and running this code (fmt version 6.2.0, clang version 10) produces the following output:

hello  # the regular std::cout
terminate called after throwing an instance of 'std::__ios_failure'
  what():  basic_ios::clear: iostream error

I'm not familiar with iostreams, so maybe the FormatGuard is at fault here and you should tell me to go away 😛 . But I thought I'd ask if you had anything jumped out to you.

vitaut added a commit that referenced this issue May 7, 2020
@vitaut
Copy link
Contributor

vitaut commented May 7, 2020

I don't know why copyfmt throws when exception mask is set but I implemented a workaround in 8f511fc by setting the mask after operator<<. Thanks for reporting.

@vitaut vitaut closed this as completed May 7, 2020
@vitaut
Copy link
Contributor

vitaut commented May 7, 2020

And here's Billy O'Neal's explanation why the exception is thrown:

Ah, there badbit is still set because rdbuf() == nullptr, and you turned on the exception mask asking for badbit. The call to exceptions(value) inside copyfmt is attempting to clear the flags but clear() forces badbit back on when rdbuf()==nullptr

@suo
Copy link
Author

suo commented May 7, 2020

Thanks for such a quick fix :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants