3 ms·
Every complaint about a goto is valid for try..catch, except it's worse because it's a non local goto for which the destination is unknown at compile time. Ugh.
by notacoward 8y ago
Every complaint about a goto is valid for try..catch, except it's worse because it's a non local goto for which the destination is unknown at compile time. Ugh. Yesterday I had to deal with a piece of code that relied on a certain exception to do a particular kind of repair, but someone had added a different exception twelve layers down (and across an RPC boundary). This was much harder to debug than it would have been with error returns, because nothing in those dozen intermediate layers had a chance to see and log the new exception. It just flew right by them, and when it arrived at its destination there was no information about its provenance. Thus, I had to go through a tedious process of instrumenting each layer to see how far it got before the flow of control was yanked away from it, which took hours instead of the minutes it would have taken to step through the same thing with error returns.
I know there are some techniques that could have made that experience better, but this kind of crap seems to happen every time I have to interact with a codebase that relies on exceptions as a primary error-handling mechanism. That means practically all C++ and Java where it's strongly idiomatic, and some Python where it's more weakly so. Error returns might be more verbose, but they're ultimately better for maintainability.
- edflsafoiewq 8y agoFrom the CFG perspective, try..catch is strictly weaker than goto (you can't build irreducible control flow with it for example). And, I mean, any return is basically a non-local goto for which the destination is unknown at compile-time. Your story seems strange since I think one of the best features of exceptions is that if you don't catch them, you always get a full stack trace which is a great boon for debugging. If you bubble up error returns, the only contextual information you get about where the error occurred is what every caller attaches to the return. But I have had terrible trouble getting stack traces (or types) from Python exceptions when they cross a process boundary so maybe that's it. (I have no strong opinion about whether exceptions are good or bad myself.)
- notacoward 8y ago> you always get a full stack trace You get a trace from where it was caught. Where was it thrown? Nobody knows. To be fair, that's the same as you'd get with error returns, but at least those dozen layers in between had a chance to see and log the error. Or in a callback-based system you do get a trace from where the error originated. The problem is that the act of throwing an exception destroys practically all information other than what you put in the exception yourself, and very few programmers implement exceptions in a way that provides as much information as is already available with error returns. Exceptions should be exceptional - rare events that don't get thrown or caught as part of normal operation. When every possible outcome of calling a function is reflected as a different exception, even if it's a fairly common case, that's when even simple control flows turn into big piles of random jumps.
- edflsafoiewq 8y agoNo, you get a trace to where it was thrown.
- anyfoo 8y agoIn C++?
- edflsafoiewq 8y agoYes? Is there a difference in terminology here? Obviously you get a trace to the point of the throw. ~ $ cat a.cxx int a() { throw "a"; } int b() { return a(); } int main() { b(); } ~ $ clang++ -g a.cxx && gdb -ex r -ex bt a.out < ...snipped... > #6 0x0000555555554779 in a () at a.cxx:1 #7 0x0000555555554789 in b () at a.cxx:2 #8 0x000055555555479d in main () at a.cxx:4
- anyfoo 8y agoThere is no catch in your example. I thought the point was that in C++, preserving the stack trace when having caught an exception is rather non-trivial. Exceptions that don't get caught usually allow you to get the stack trace through a crash report/core dump/whatever, but then there's not much difference between an uncaught exception and a plain abort().
- edflsafoiewq 8y agoYes, I said "if you don't catch them you always get a full stack trace". The comparison was between returning error values and exceptions, not between exceptions and abort. The difference is with abort is of course that once you are alerted to the error by seeing it be uncaught, you can insert an appropriate handler for it. A file-open function can throw on file not found but I will not very happy if it aborts.
- anyfoo 8y ago