Earlier quoted context omitted.
> They generate syntactic noise at every point they touch the call graph: function signatures, calls, returns. This is not "noise" but needed information. A function that can error out should not have the same signature as one that will never return an error. Similarly, call-site special syntax (like '?' in Rust) helps address the concerns raised by hidden control flow. > Since the caller must be aware of them, gener…
I agree that functions should specify in their signature wether and how they fail, but checked exceptions can do that. Additional call site syntax is indeed just noise. I strongly agree with David Abrahams[1] on this. A better solution would be noexcept regions were the compiler would statically guarantee that they can't be left via exceptional control flow. [1] https://forums.swift.org/t/on-the-proliferation-of-try-…
Current hardware trends make C++ exceptions harder to justify
281–290 of 516 posts
Re: Current hardware trends make C++ exceptions harder to justify
#282Earlier quoted context omitted.
That argument is only true in single threaded applications, at least given today's exception implementations. The more threads you have, the more problematic exceptions become. On the large machine you start to see performance problems with 0.1% failure rate, which is not that much. An core counts continue to rise.
Again, most experienced C++ programmers would say that even a 0.1% "normal" failure rate indicates a situation that should not be handled by exceptions. You seem to be describing a style of programming where there's a bunch of work to be done, most efforts to do the work will succeed, a few will predictably (albeit randomly, perhaps) fail. While I would concede that you might conclude that exceptions are the perfect…
I reserve exceptions for a really exceptional situations.
My motto is that if an exception happens, the program should crash since it's an unrecoverable error. That's just my opinion by I try to enforce that in my own codebase.
My main beef with exceptions is that sneak past the type system. Unlike Java with its exception specification, in C++ we have no idea what to catch. Yes, there's documentation, but it's often hard to keep it in sync with the code. I've been bitten many times in the last couple of years by surprising exceptions jumping from deep inside innocent function calls, either because of a deep dependency or because someone just threw one and didn't document it (that someone was also a younger me on occasion...)
So my design criteria for exception is, is this error here unrecoverable for the application?
The 2 examples in OP's paper are 2 functions, and we have no context. If they were a part, say, of a console application that was used in a nightly cron job, and there was no user to ask for proper input, then yes, maybe crashing the application is acceptable. I would still have liked to print something to a log.
If this was a part of an interactive program, then a proper error code / std::optional / other error object about the illegal value and its place in the array should be returned, with a proper error message displayed to the user about logged. This I'd do by having a top-level catch handler. A single one for all the application.
Re: Current hardware trends make C++ exceptions harder to justify
#283Earlier quoted context omitted.
> Panics do not need to be caught and handled. You can (and should) transform panics into abort. I think this strong stance needs some justification, especially since it's not the default in Rust.
It is in Go Lang which shares error handling philosophy with GP.
"For a real-world example of panic and recover, see the json package from the Go standard library. It encodes an interface with a set of recursive functions. If an error occurs when traversing the value, panic is called to unwind the stack to the top-level function call, which recovers from the panic and returns an appropriate error value (see the ‘error’ and ‘marshal’ methods of the encodeState type in encode.go)."
Re: Current hardware trends make C++ exceptions harder to justify
#284I find this paper quite unconvincing. Exceptions are exceptional so in principle it doesn't matter (within reason) how long it takes to throw one as long as it costs nothing not to do so. So measuring the cost of repeated throws IMHO doesn't cast light on any useful case, and the approaches that add runtime cost for the path not taken, even Herb Sutter's, are not acceptable. His code transformation example is simply…
"exceptions are exceptional" means what?
Re: Current hardware trends make C++ exceptions harder to justify
#285Earlier quoted context omitted.
C++ is still a wonderfully performant language, and there are still domains where it is clearly a leader (networking, games/graphics, etc). Rust is slowly displacing it but there's still a lot of road left. The maturity, stability, prior art are also worth something. The pitfalls are really not that big and dangerous, although to someone who doesn't do C++ I can see why it has that perception. Additionally, if you ar…
More people start using C++ professionally in any given week that the sum total paid to code Rust. Rust is not "displacing" C++ anywhere beyond the HN echo chamber.
Re: Current hardware trends make C++ exceptions harder to justify
#286Earlier quoted context omitted.
When something happens that violates your assumptions about your own program's behavior, throwing it into a state where it doesn't know what happens next. Kind of like a panic.
This would mean that attempting to open a file that doesn't exist shouldn't throw an exception. But that is exactly what it does in the standard libraries of many languages with exceptions.
Re: Current hardware trends make C++ exceptions harder to justify
#287I find this paper quite unconvincing. Exceptions are exceptional so in principle it doesn't matter (within reason) how long it takes to throw one as long as it costs nothing not to do so. So measuring the cost of repeated throws IMHO doesn't cast light on any useful case, and the approaches that add runtime cost for the path not taken, even Herb Sutter's, are not acceptable. His code transformation example is simply…
"exceptions are exceptional" means what?
This is in contrast to say python where the convention is to rely heavily on exceptions as part of the normal flow of the code, sometimes described as "asking forgiveness, not permission". It is not uncommon for a method argument to support multiple types, and to discern them by treating the object like one type and if you get an exception, then try treating it like another type. Likewise, if you're not sure an item is in a dict, you just try to access it, and catch the exception if it isn't. This has performance impacts, but so does everything else about python, so it isn't worth optimizing.
Re: Current hardware trends make C++ exceptions harder to justify
#288I find this paper quite unconvincing. Exceptions are exceptional so in principle it doesn't matter (within reason) how long it takes to throw one as long as it costs nothing not to do so. So measuring the cost of repeated throws IMHO doesn't cast light on any useful case, and the approaches that add runtime cost for the path not taken, even Herb Sutter's, are not acceptable. His code transformation example is simply…
"exceptions are exceptional" means what?
So if you are trying to hold a lock you don't throw an exception, you just wait and try again. Perhaps you can't reach that host; try again a few tiles before giving up and throwing an exception. But if you try to write to removable media and the device won't open, all, your program isn't going to mount a tape itself: throw an exception and let the problem be handled at a higher level.
Re: Current hardware trends make C++ exceptions harder to justify
#289> The second problem could potentially be fixed by a sophisticated implementation, but that would definitively be an ABI break and it would require careful coordination of all components involved, including shared libraries.
This seems like a perfect application for an rwlock. Threads that throw acquire for reading, so can occur in parallel. Threads that load or unload shared libraries (a pretty rare occurrence outside of process start) acquire for writing and therefore block reads from the table from throwing threads. The shared library loader shouldn't throw during this piece.
Come to think of it, throwing should also be pretty rare. C++ exceptions are not really about common control flow, but truly exceptional circumstances. So the high cost serializing parallel throwers doesn't even sound like that huge of a deal. But as I've said, it seems pretty easy to improve upon it.
[Edit: It would seem the article does say something about how an rwlock is not feasible with the current implementation ... It doesn't sound terribly convincing]
Re: Current hardware trends make C++ exceptions harder to justify
#290Earlier quoted context omitted.
> By people who do not want to believe that errors are part of a system's API… The point was that you should be returning errors, not throwing them. Runtime exceptions (null reference, division by zero, out of memory, etc.) ought to indicate a fatal error in the (sub)program or runtime environment. You can trap these, and report them, but it's usually a mistake to try to case-match on them. Unlike errors, which are p…
I disagree with this. But, I'm also a fan of the condition system in Common Lisp. That is, if the problem is likely one that needs operator/user intervention, the non local semantics of exceptions makes a ton of sense. Indeed, it is useful to have a central handler of "things went wrong" in ways that is cumbersome if every place is responsible for that.
The condition system in Common Lisp (which I am also a fan of BTW) is designed around dealing with conditions when they occur, whereas most of the alternatives focus on the aftermath. In particular, conditions don't unwind the stack before running their handlers, which makes it possible to correct the issue and continue, though handlers can naturally choose to perform non-local returns instead. More to the point, there is no requirement to annotate Common Lisp functions with the conditions they may raise, which makes them more akin to unchecked exceptions.