4 ms·
Honest question: why use exceptions at all? They seem like far more hassle than benefit. Why not just use explicit error handling? This also results in much, mu
by PittleyDunkin 2y ago
Honest question: why use exceptions at all? They seem like far more hassle than benefit. Why not just use explicit error handling? This also results in much, much, much more readable code.
- kllrnohj 2y agoBecause they are just better for the actual rare issue. Consider for example out of memory. "proper" error handling via return values would mean everything that allocates memory has to have an error return path and everything that calls anything that has that somewhere in the chain needs to still propagate that error. Essentially every function call now has a branch after it. If done explicitly, that's a lot of code nobody wants to write and, more importantly, that nobody ever actually tests. If done automatically, that's still just a metric shitload of branches which wastes branch predictor entries, it wastes cache size, etc... Exceptions, meanwhile, are typically free unless actually thrown. So for the truly 0.001% situation, like the aforementioned out of memory, they are perfect. You also get stack traces for free which greatly aid in debugging. Also typically you either handle errors pretty close to where the occur, or relatively high up at a more macro level. Exceptions lets your "middle" layer be significantly less branch-y & verbose for situations where it's a more macro-level error handling strategy. The alternative approach, like what Rust does, is to just say that rare errors like that are unrecoverable and hard-crash when encountered. That's certainly a choice you could make, but it's pretty heavy-handed for the language itself to mandate that. Which is then why Rust also provides std::catch_unwind, but with notes that it doesn't necessarily work because people can have chosen to compile with panic set to hard-abort period. It's pretty much a big mess.
- PittleyDunkin 2y ago> "proper" error handling via return values would mean everything that allocates memory has to have an error return path and everything that calls anything that has that somewhere in the chain needs to still propagate that error. That seems like a win to me for the aforementioned "readable" criteria—failures should be enumerated. But I can see how that would be annoying to write. I'm also of the opinion that if handling out of memory is a serious consideration for your process, you should consider using your own allocator that doesn't fire an exception. This is how rust handles it, for instance. And on top of this I'm a little confused because exceptions are mostly disallowed from embedded codebases, which is the primary place where you would likely run out of memory and want to actually handle it.
- ryandrake 2y agoDisallowing exceptions is a company policy, though, not something imposed by the language. I'm not going to go into whether I think it's a good or bad policy, but just pointing out that you can write embedded software that properly handles exceptions. Granted, the discipline, will (and yes, budget) to do this is pretty rare in embedded shops.
- PittleyDunkin 2y agoWell, that's rather beside the point—if you're really worried about allocators failing, exceptions don't provide any benefit over simply returning NULL.
- kllrnohj 2y ago> exceptions don't provide any benefit over simply returning NULL. Sure they do - they don't negatively impact the non-error case and don't pollute every function's return value.
- surajrmal 2y agoSignificant chunks of the c++ community also compile with exceptions disabled, turning them into asserts. Handling some errors in band is simply not useful in modern programs. While kernels and embedded use cases benefit from in band allocation failures, most applications would do better to receive an out of band signal that they are close to memory thresholds and to perhaps shed load by doing things like stop accepting new sockets connections, shrink some caches, etc. I really used to think otherwise but too much software has been written to assume they will never experience a memory failure in band. Also to clarify, I don't think an exception is out of band. They have a significant cost to program size and performance even if they are never used.
- kllrnohj 2y ago> They have a significant cost to program size and performance even if they are never used. They do have a cost to program size, yes, but they have ~zero impact on performance when never used. They are completely cold, outside of normal flow.
- jandrewrogers 2y ago"~zero" is not zero. The existence of exceptions forces changes in the design of normal code to allow for that possibility, which does have a runtime cost. Some objects cannot be safely destroyed at arbitrary points in the program without additional logic to mitigate side effects. Exceptions don't eliminate error checking conditionals, they just hide them elsewhere in the code.
- kllrnohj 2y agoCan you provide an example of that on godbolt or similar? In what scenarios do exceptions introduce the claimed cost? The only thing I could see is just the density of code could mean more page spills and less efficient cache line usage for code. There's otherwise no actual cost to the assembly executed itself. And that's compared to no error handling at all, even. Compared to return values it's very clearly faster. But maybe there's some edge case you're aware of that does something different.