41 ms·
The article is mostly about exceptions, which is fair I guess. However, by the time you write C code that handles _all_ errors (like exception handling would),
by fefe23 8y ago
The article is mostly about exceptions, which is fair I guess.
However, by the time you write C code that handles _all_ errors (like exception handling would), you end up with code that does not look as nice as the examples given here. In production C code you often end up seeing a "goto fail" or "goto done" and then hand-written destruction of objects. To make that less error prone, you have to explicitly initialize everything in the beginning of the function. Oftentimes you even see the "goto fail" invoked via a macro.
Now, in my humble opinion, by this time you might as well have used C++. Persponally, I do like the regularity of such code when reading other people's code. Still. It's a lot of effort. And the benefits over exception handling are not so obvious to me. You end up restricting yourself in both cases.
Also, when considering whether constructors and destructors should throw exceptions, consider the array case. You instantiate an array of 100 foo. If constructor #42
throws, how do you know which ones have been initialized and which ones haven't? Even worse, if you delete[] an array and one of the destructors fails -- do you get memory leaks? Maybe the destructor was supposed to release a mutex and you can get deadlocks?
I find it very telling that both C and C++ (and most other languages for that matter) end up defining a "good subset" that you are supposed to stay inside. You would be forgiven for concluding that we don't know what we are talking about when we design new languages, and we should not hastily add new features lest we end up having to recommend against them in the future. Yet, many languages (I'm looking at C# and Javascript here) keep getting new features on a yearly basis.
I think we should be much more sceptical.
I also think this is a dilemma that is similar to the startup dilemma. It is a very risky proposition, so the people who end up doing it are not risk averse and tend towards the "hold my beer" part of the spectrum.
- Paul_Diraq 8y agoI think it is perfectly fine that destructors can't throw. For the rare cases that you need finalizers which might throw I would go for something inspired by pythons with statement. WITH(expr , lambda) expands to(sketch): bool _exception_happened=false; auto __temp = expr; __temp.enter(); try{ lambda(__temp) }catch(const std::exception & ex){ exception_happened = true; __temp.exit(ex); } if (not exception_happened){ __temp.exit(); }