C++11: Try/Catch/Finally Pattern Using RAII & Lambdas
nerds-central.blogspot.com
nerds-central.blogspot.com
This is a very nice small implementation but, as always with C++, devil is in the details:
* Creation of an std::function needs a dynamic allocation, so if the allocation fails an exception will be thrown and if the finally is guarding a resource, the resource will be leaked
* std::function has a non-negligible calling overhead, hence this should not be used in performance-sensitive code
* Checking a condition inside the finally clause is not very elegant, a better idiom in C++ is to support dismissing a scope guard.
* The finallyClause may throw an exception, and since it is called in a destructor this is generally considered a bad idea. I don't know what could happen in this case, but some scope guard implementations I've seen catch the exception and explicitly call std::terminate(). I guess this is for performance reasons, because the destructor can be declared nothrow.
Here there is a more complex implementation, which addresses most of the corner cases:
http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stepha...
As for memory allocation failures, my experience is that depends a lot on the platform. It is a common misconception that dynamic memory is likely to run out and therefore we need to worry about that but not automatic memory. However, I have seen stack overflow many many many more times than a genuine 'out of memory'. Further, if an application has actually run out of memory so badly that a allocation of the closure's internal storage barfs then I suspect it cannot be retrieved. Naturally this does not apply if your platform has a very low heap size (e.g. realtime hardware or some such).
~finally() {
finallyClause();
}
This allows exceptions thrown by finallyClause() to propagate out of the destructor, which, if an exception is already being thrown, will result in a call to std::terminate(), causing the application to die horrifically. Because C++ kinda-should’ve-but-really-doesn’t have checked exceptions, we must simply discard them: ~finally() {
try { finallyClause(); } catch (...) {}
}
You can also avoid problems with exceptions and std::function’s dynamic allocation by using a template instead: template<class F>
class finally_type {
public:
explicit finally_type(F f) : function(f) {}
~finally_type() { try { function(); } catch (...) {} }
private:
finally_type(const finally_type&);
finally_type& operator=(const finally_type&);
F function;
};
template<class F>
finally_type<F> finally(F f) { return finally_type<F>(f); }
This can be used like so: void test() {
int* i = new int;
auto cleanup = finally([i]() { delete i; });
may_throw();
}
Finally (har!) the equivalent idiom in C++03: void test() {
int* i = new int;
struct finally {
finally(int* i) : i(i) {}
~finally() { delete i; }
int* i;
} cleanup(i);
may_throw();
}I am guessing this is the situation?
This would make the error pass silently, possibly leaving the program in an inconsistent state. It is probably better to call std::terminate() instead, which is what C++ does when an exception is thrown when another exception is active.
~finally_type() {
try {
function();
} catch (...) {
std::throw_with_nested(std::logic_error
("Exception thrown from \"finally\"."));
}
}
It might pollute calling code a bit with calls to std::rethrow_if_nested(), but I think it’s worth it for the safety.Hence, in most cases where the scope guard pattern is used (to guarantee exception safety), your code is basically equivalent to calling std::terminate().
But anyway, the problem is still programmer error. Just as you shouldn’t throw an exception from a destructor, you shouldn’t throw an exception from a “finally”, because it is, by definition, run in a destructor. So, sure, calling std::terminate() explicitly makes about as much sense as anything, but I’d prefer to ignore (and perhaps log) such erroneous exceptions, for reasons of stability.