3 ms·
I theoretically like exceptions, and used to extol their virtues, but I've come to hate them in practice. They're an endless source of fustration in that the A
by MaulingMonkey 7y ago
I theoretically like exceptions, and used to extol their virtues, but I've come to hate them in practice. They're an endless source of fustration in that the APIs you least expect will throw various unexpected exceptions for various undocumented edge cases, which invariably leads to heisenbugs crashes in our bug tracker that I need to go waste a few hours trying to repro and root cause because I, foolishly, was a good boy who didn't spam catch(Exception) everywhere (as that would also catch the null/index exceptions indicating real bugs). Theoretically, forcing you to use checked exceptions would solve this, but would defeat many of the supposed virtues of exceptions.
I also frequently get stuck refactoring a lot of code other people have written because an exception tried to unwind across an ABI boundary, and nobody thought about how to handle that or what would happen. That ABI could be across a C module, which has no exceptions. Or perhaps across a C++ module built without exceptions, or using an incompatible unwinding mechanism. Cleanup gets skipped, undefined behavior gets invoked... it's a mess.
So, invariably, I write some catch(Exception) equivalents, if only to manually write the code to explode loudly and in a way condusive to debugging, instead of much later when the stack trace has been mulched through rethrows, or access violations from the UB, or ...
Now compare and contrast that to error codes, which I theoretically dislike, but swear by in practice.
Error codes are C ABI safe, any language can return them, set them, or store them. They're part of the method signature, neglected documentation be damned. There won't be any exotic failure modes where C++ destructors get skipped due to a setjmp style unwind. Even the absolute worst APIs usually have some kind of incomplete list about failure modes - a list of constants somewhere - and I have a fighting chance of deciding upon a sane local fallback (on top of breakpoint/logging/reporting) in the event of an undocumented/unexpected error code.
My biggest concern was always accidentally ignoring an error code, but every language at least has compiler extensions these days - to mark a function result as needing to be used - and a way of turning that warning into an error. Does this sometimes lead to a little extra error handling boilerplate? Yes. Does that even enter into the top 10 issues I have with error handling code? No.
I do get the occasional bug where ignoring an error code contributed to it's occurance, but those are a small price to pay compared to avoiding all the bugs arising from exception (mis)use I avoid.