6 ms·
Author asserts that "The decoupling between raising of the exception and handling it, that makes avoiding failures so easy in C++, makes it virtually impossible
by jcelerier 7y ago
Author asserts that "The decoupling between raising of the exception and handling it, that makes avoiding failures so easy in C++, makes it virtually impossible to guarantee that the program never runs info undefined behaviour." (and all the woes he encounters afterwards stems from trying to avoid exceptions due to that assertion).
But that is not my experience at all. Exceptions are much more reliable than error codes - there will always be a case where you forget to propagate an error you got, but you cannot "forget" to propagate an exception... (and if you do, you can always run a debugger post-mortem to get a nice stacktrace of where the exception was thrown - `coredumpctl gdb` is a super nice tool for that on Linux systems with systemd). And languages without exceptions just end up with a galore of `if err != nil { panic(err); }` or similar horrors...
Also, regarding "compiler is likely to produce more efficient code.", benchmarks have shown that exceptions are generally faster : http://nibblestew.blogspot.com/2017/01/measuring-execution-performance-of-c.html http://nibblestew.blogspot.com/2017/01/measuring-execution-p...
- rectang 7y ago> there will always be a case where you forget to propagate an error you got Not if the ecosystem supports Result types a la Rust (and others). You don't get to access the return value unless you deal with handling the error first.
- jcelerier 7y ago> You don't get to access the return value unless you deal with handling the error first. Well, that's exactly what I was referring to. 80% of the time you don't / can't know what to do with the error at a given call site, so from what I could see, either people end up doing nothing and "abandoning" the error (bad) or panicking (worse). It's better to just let the error go transparently so that if someone actually can do something meaningful upper in the call stack, it's possible. source : https://github.com/search?l=Rust&q=panic&type=Code https://github.com/search?l=Rust&q=panic&type=Code
- deleted 7y ago[deleted]
- steveklabnik 7y agoHm, we must read very different Rust code. ? is even easier than a panic. And that search has a ton of false positives: both in general, as well as "unwrap" being the more common way to get a Result to panic.
- jcelerier 7y agoc'mon... $ cd servo/components $ rg -F 'panic!' | wc -l 276 Likely a fair amount is justifiable, but things like this ? https://github.com/servo/servo/blob/master/components/script/dom/bindings/structuredclone.rs#L74 https://github.com/servo/servo/blob/master/components/script... or this https://github.com/servo/servo/blob/master/components/gfx/platform/freetype/font_list.rs#L96 https://github.com/servo/servo/blob/master/components/gfx/pl... ? that's a really strong code smell (or at least doing a similar thing in a C++ program, e.g. calling abort() / SIGTRAP, would be, even with a signal handler, a really really really long discussion in code review)
- steveklabnik 7y agoloc in that same directory says 289958 lines of Rust code, that is a ratio of 0.00095186199. That is pretty small. 175 unwraps, which I am actually shocked is smaller than panics. And yes, I do think that both of these are pretty justifiable: both of these are effectively assertions, which is not unheard of in C either.
- jjnoakes 7y agoPeople may do it wrong in rust but I personally like that rust gives me the tools to handle errors in my preferred way: explicitly passing them up the stack with minimal verbosity (using ?) or explicitly having to handle them in some way. I don't like verbose error checking on every function call which is ugly and which I might forget to pass up (c-style) and I don't like exceptions which aren't expicit and which I might forget to handle locally if I wanted to.
- usefulcat 7y ago> you cannot "forget" to propagate an exception Not only that, but you don't have to write a ton of boilerplate to manually propagate errors back up the stack since the compiler will do that for you. And it will do it in a consistent, well-defined manner.
- wvenable 7y agoFurthermore, properly structured C++ applications with RAII use the same path for normal cleanup for exceptional cleanup meaning that you're always covering that code. You don't have an entirely separate error handling path that only gets executed for errors.
- irishjohnnie 7y ago> benchmarks have shown that exceptions are generally faster The blog post you linked to says "Immediately we see that once the stack depth grows above a certain size (here 200/3 = 66), exceptions are always faster. This is not very interesting, because call stacks are usually not this deep (enterprise Java notwithstanding). For lower depths there is a lot of noise, especially for GCC ..." So ... not exactly "generally faster". Also, the test is only for Linux. The same test on Windows/VC++ will probably run a lot slower ... again not "generally faster"
- jcelerier 7y agoLook at all the results. Even before that exceptions are more often a win than a loss. > The same test on Windows/VC++ will probably run a lot slower ... By default on 32-bit, with SJLJ exceptions, that's likely. But on 64-bit windows the default exception handling (SEH) uses a similar mechanism than Linux and should have comparable performance.
- irishjohnnie 7y ago> But on 64-bit windows the default exception handling (SEH) uses a similar mechanism than Linux and should have comparable performance. AFAIK SEH in Windows calls RaiseException() which in turn causes a user/kernel mode transition, probes for exception/termination handlers, and vectored exception handlers depending on the severity. It's been a while but I'm not sure the code GCC generates in Linux is quite like this.
- irishjohnnie 7y agoI missed this in my previous reply ... > Look at all the results. Even before that exceptions are more often a win than a loss. The blog post you linked to effectively says "it depends"
- aidenn0 7y agoZeroMQ is a library to be called from other languages. You do not want to ever accidentally throw an exception from C++ to a function that is called from outside C++.
- usefulcat 7y agoThat’s fine, the library can catch exceptions at the boundaries of the C API. That’s still usually going to be a lot less tedious than manually propagating error codes all over the internals of the library.