11 ms·
I wish they were more specific about when to use and not use exceptions. Truth be told I really hate exceptions and I strongly feel that they should only be us
by _xzxj 9y ago
I wish they were more specific about when to use and not use exceptions. Truth be told I really hate exceptions and I strongly feel that they should only be used in the most disastrous situations. I'm messing with the 0MQ C++ wrapper now (which I will probably move off of) and they use exceptions for freaking everything. For example the send(msg) method returns true if the message is sent, false if EWOULDBLOCK is returned by the C api, or throws for any other error.. Like guys shit happens on networks all the time, just give me an error. Instead I have to try to track down all the damn exceptions and figure out what throws and what doesn't..
I actually really liked the way Apple did it for Objective-C. Don't use exceptions unless something is really going sideways, instead use NSError. I'm not saying this is the correct pattern for C++, but I don't personally think exceptions are the correct pattern either.
- _sdegutis 9y agoThe way ObjC did it is to use exceptions to signal programmer error, and error objects for program errors. I think it’s the best style, at least until the day programmer errors just won’t compile , but that needs something like Idris to take over.
- deleted 9y ago[deleted]
- ilammy 9y agoTo be fair, it's not always true. Many APIs actually don't have NSError argument and throw Obj-C exceptions on actionable errors. For example, reading from an NSFileHandle may throw NSFileHandleOperationException. I suppose, in most cases it has been done for brevity. Though, you can also argue that only opening a file could fail (due to invalid path or insufficient permissions).
- mehrdadn 9y ago> I wish they were more specific about when to use and not use exceptions. Do you have any examples in mind where it's unclear to you whether an exception would be appropriate?
- jgh 9y agoNo because I almost never use exceptions myself (unless consuming them). The only time I would really use it is if for some reason the constructor could fail, but usually in those cases there are better ways of designing the class. Otherwise it's error codes/reasons. Honestly I'm not sure where to draw the line specifically, but I obviously err more on the side of "don't use them". Exceptions in C++ are costly and imo control flow gets all wonky with them...I find it's easier to reason about a program if the error handling is there with the rest of the logic instead of being a list of things that can happen at some point in the above code block.
- AstralStorm 9y agoAny error handling will make control flow explode into checks. Exceptions at least allow you to put the checks in the right place and not necessarily at the point where function is executed. In typical C code you get to propagate error check statements all the way everywhere or risk bugs. Or use central mechanism like errno and risk thread safety and overwrite while also not knowing about the source of the statement. In C++ you might have the same problem. Even std::optional (which defers the exception to actual value get) is not best as it loses the information on who made or set it...
- blub 9y agoCalling get on an empty optional is a programmer error though, not unlike dereferencing an invalid ptr, so throwing would be an improvement. :) Most code would check or call value_or, buggy code would throw. There's still the complication of the unsafe std::optional interface, which can only be solved by wrapping/rewriting IMO.
- ovao 9y agoBjarne's guidance has always been to use exceptions only in truly exceptional circumstances. A function that might occasionally fail on bad user input could instead return a std::optional and be marked noexcept (assuming it really doesn't throw). A function that fails to allocate memory, on the other hand, is truly exceptional, so throw std::bad_alloc. The STL unfortunately doesn't always follow this approach, and tends to overthrow. Signaling why something failed without exceptions is still unnecessarily tricky in C++. Not because it can't be done, but because there's no standard guidance on how to do it. There are 3,385 ways to do the job, so in many cases it's better simply not to.
- jgh 9y agosince optional is a thing now and the standards committee isn't afraid of verbosity maybe we can get std::value_or_error ;)
- throwaway84742 9y agoLike Google StatusOr<>?
- jgh 9y agoMaybe? I'll take a look at it!
- AstralStorm 9y agoLike std::future right? You can use that one today.
- blub 9y agoNope, a result<T,Err> like expected-lite on github.
- RotsiserMho 9y agoYou might be interested in Boost.Outcome (v2) or the proposed std::expected.
- 112233 9y agoSo nice to see that attitude. Exceptions, as implemented in C++, turn it into a dynamically typed language. If working with code written by others (libraries, big project), it is really hard to reason about control flow if every function call is potential return statement. It is not exactly easy to read top level error handling code either: catch (Pig) { // now Grunk need find pig. The amount of frame unwinding code generated can get really big, etc. I wish C++ provided means to preallocate memory for handling task (2 buffers for 4k, map for N objects of type T, ..., ok? then run this). Instead, there is a russian roulette powered default allocator, that can out-of-mem at any time...
- jcelerier 9y agomost containers have a "reserve" method which does this. for maps you can use boost's flat_map (ordered) or ska::flat_hash_map (hashed) which both use linear storage that you can reserve. and if for some reason you can't you can still pass your own allocator with preallocated memory, or use boost::pool_allocator
- 112233 9y agoRight. My point was that there is no mechanism to do top level resource allocation, like exceptions do for top level error catching. Allocators are fine, but they are not enough for this, really: // big task will create map<int, int> with 1000 elements MyAllocator a; a.reserveMemory(????); // <-- what to put here? bigtask(a);
- jcelerier 9y ago> My point was that there is no mechanism to do top level resource allocation How could it make sense if bigtask(a) is a separate function, maybe in another DLL / shared object ? Maybe bigtask is not even written in C++ but in C, Rust, D, whatever. Maybe it's not even using malloc but directly OS primitives.
- 112233 9y ago
- snarfy 9y agoExceptions are a mistake, plain and simple. They should have never been added to the language. They break the notion of programming as a sequence of events. With exceptions, now you have two sequences, the happy path and the 'wherever the hell the exception is caught' path. No matter how you slice it, exceptions are still a goto under the covers. If they are truly exceptional, you might as well call exit() too. Go got this right. If there is an error, return it to the caller. The error can be a function, and the caller can call it when they want. This returns programming to a single sequence of events.
- krylon 9y agoWell, strictly speaking, Go has panic() which is very similar to exceptions. But it also has a culture that strongly discourages using it unless things go very wrong.
- dullgiulio 9y agoNo, think of panic() as unhandled Segmentation Fault (and other Go specific unrecoverable errors). You can handle Segmentation Fault, but you need to know what you are doing. In Go it's the same.
- quotemstr 9y agoPanic is _semantically_ the same as throw. That Go culture treats panic like evil voodoo doesn't change how the language construct works.
- PopsiclePete 9y agoNobody in Go culture treats it as "evil voodoo" that I'm aware of. There are clear guide-lines. User passes in a path to a file that doesn't exist and you attempt to open it? Return an error. That's not "exceptional" or "programmer error" - it's just normal "shit happens". You have an array-like structure with 10 elements and your function that modifies it gets passed in index 13? That's probably a bug or programmer error, not "user" error - so panic. Go documentation is very clear on the difference between the two, actually. I've never been confused.
- quotemstr 9y agoI strongly disagree with you. I think too few people use exceptions. They're great for making code more expressive, and it's only through exceptions that you can avoid two-phase initialization of classes and make constructors actually useful. It's only through exceptions that you can have meaningful copy-constructable resource-holding value types. Avoiding these constructs severely restricts the language. And for what? The arguments against exceptions appear to mostly arise from misunderstanding or some kind of weird aesthetic sense that I don't have. Error codes also generally discard context and encourage a "just abort" mentality, especially with respect to memory exhaustion. That, or they become so general, mechanized, and macro-ized that they might as well be exceptions, but worse in almost every way. Exceptions are your friends.
- lasagnaphil 9y agoAbout the dependency between constructors and inheritance, I like how rust handled the situation. In rust you do not have any constructors, but instead you can make a factory method that returns an Option<T> or Result<S, E>, so no need for any exceptions while construction. You can also do this in C++, but you still have to declare constructors anyway, along it being a bit inconsistent with other idiomatic C++ code...
- mehrdadn 9y ago> It's only through exceptions that you can have meaningful copy-constructable resource-holding value types. Could you give an example of this specifically? Are you thinking of e.g. a File class whose constructor opens the file? Because every such example I can think of is one where it ultimately seems inappropriate to me to use exceptions to signal the error. Both from a conceptual standpoint (it might be something you have no control over, so it's not a programmer error) and from a performance standpoint. Example for the latter: say the user gives you a list of hundreds of thousands of files that are to be copied somewhere "if they exist". Imagine half of them don't exist. Now your program is going to have to run through hundreds of thousands of exceptions to signal this.
- pknopf 9y agoPeople gripe at Go's error checking, claiming it's verbose, etc. But, I like it. Fully and clearly expressed intent for the handling of errors.
- krylon 9y agoIn a programming language that allows functions with multiple return values, error values of some sort become almost natural. In Lua, the idiom of returning "nil, errormessage" on failure is very common, too.