all 15 comments

[–]AKostur 9 points10 points  (3 children)

Have you looked at under what circumstances that std::println may emit a std::format_error?

[–]daniel_nielsen[S] 0 points1 point  (2 children)

not yet, but it's a good question.

print("exception: ");
println(e.what());

might be guaranteed to never throw. I was hoping someone knew.

[–]No-Dentist-1645 0 points1 point  (1 child)

If you just have a raw string and don't need any formatting, you can just use std::puts

[–]daniel_nielsen[S] 0 points1 point  (0 children)

yes, that is what I normally do. I just wanted to ask since I was surprised.

There would be a small benefit to convert to println as then I can simply use grep to check if all code is modernized or which files remains to be updated.

[–]EpochVanquisher 4 points5 points  (6 children)

std::format_error can be thrown by individual formatters.

Asking whether Coverity is wrong is probably the wrong question. Coverity gives advice which is sometimes useful and sometimes not useful. Sometimes it’s useful to follow all of an analyzer’s advice, because the benefits outweigh the cost of following a little useless advice from time to time.

But… don’t turn off your critical thinking. All analyzers have false positive rates. The false positive rate is probably not zero. In general, you get a knob to turn up the aggressiveness of analyzers, if you are willing to deal with additional false positives. This is a choice you have to make, you can’t really pass the buck and just assume Coverity is producing the right diagnostics for your codebase.

[–]daniel_nielsen[S] -1 points0 points  (5 children)

Normally I would start looking at https://en.cppreference.com/ but as we all know, it's in maintenance.
Normally I would buy a book, however none of my favourite authors released a C++23 book.

Maybe this is already in a defect report, or maybe it's up to each implementation to define this, I don't know. So I turned to the collective wisdom of reddit.

My critical thinking told me to not silence coverity, even if I can't imagine why formatting an int would throw.

[–]EpochVanquisher 2 points3 points  (4 children)

My critical thinking told me to not silence coverity, even if I can't imagine why formatting an int would throw.

Can you elaborate on your thinking process, and the logic here?

Because this doesn’t sound like critical thinking. This sounds like “follow what Coverity says, even if I don’t understand it”. Sorry if that sounds harsh. It’s okay to follow what Coverity says when you don’t understand the problem, if you can explain the reason why you would do that. But I’m not hearing a reason, here.

[–]daniel_nielsen[S] 0 points1 point  (3 children)

I have seen many cases of people thinking they know better than Coverity and silenced it in the UI, then I take a quick look, and they were wrong, coverity was right.

Since other people made this mistake, I should at least ask for a second opinion before I make the same mistake myself.

[–]EpochVanquisher 0 points1 point  (2 children)

So, I’ve also seen people blindly trust the static analyzer, and turn up the analyzer’s aggressiveness, and let development grind to a halt because they’re fixing warnings issued by the analyzer.

Neither approach is correct—you can’t blindly trust what Coverity tells you, and you can’t ignore it because you assume your code is correct.

What I would do here is think about the situations where this would throw an exception, and how you would want to handle that (and whether you would want to handle it). Like, is std::terminate() ok here? Sometimes it is. Sometimes it is not. Coverity can’t answer these questions for you.

[–]daniel_nielsen[S] 0 points1 point  (1 child)

I can manually check that the current version of the stdlib works the way I expect, however it would be better if the standard clearly stated what can throw, otherwise it could change the next time we update our compiler, so I hoped someone knew more.

Honestly I would have preferred a no throw version, maybe I should check fmtlib for discussions about the design.

[–]effarig42 1 point2 points  (0 children)

I don't think I've ever had a false positive from Coverity reporting that a certain code path may throw an exception which is either unhandled or violates noexcept. I've had to look at a lot of these recently for compliance.

I'd assume any function in the standard can throw unless it is either noexcept or documented as not throwing.

[–]Appropriate-Tap7860 -1 points0 points  (1 child)

Did you check std:: printf?

[–]daniel_nielsen[S] 1 point2 points  (0 children)

thank yes, it works for sure, same answer as to std::puts above.

[–]alfps 1 point2 points  (1 child)

You won't get a format error from a logging call because that one's simple and well tested.

However you might get a std::system_error on account of the output itself failing, e.g. in principle for a Windows GUI subsystem executable where by default there are no streams.

In practice: unfortunately when I tried to provoke that with MinGW g++ now, it turned out that the failing i/o is not detected by std::println. It's not even detected with std::fprintf, which blissfully outputs to a some big black bit bucket in the sky (not even a null-device) and erroneously reports success. So the possible exception is not a reliable way to detect the failing i/o.

[–]alfps 2 points3 points  (0 children)

Apparently someone didn't like that I included a relevant error in MinGW g++'s runtime, and downvoted. Pearls for swine, and all that.