[MS] Defending against exceptions in a scope_exit RAII type - devamazonaws.blogspot.com
One of the handy helpers in the Windows Implementation Library (WIL) is wil::. We've used it to simulate the finally keyword in other languages by arranging for code to run when control leaves a scope.
I've identified three places where exceptions can occur when using scope_.
auto cleanup = wil::scope_exit([captures] { action; });
One is at the construction of the lambda. What happens if an exception occurs during the initialization of the captures?
This exception occurs even before scope_ is called, so there's nothing that scope_ can do. The exception propagates outward, and the action is never performed.
Another is at the point the scope_ tries to move the lambda into cleanup. In a naïve implementation of scope_, the exception would propagate outward without the action ever being performed.
The third point is when the scope_ is destructed. In that case, it's an exception thrown from a destructor. Since destructors default to noexcept, this is by default a std::. If you explicitly enable a throwing destructor, then what happens next depends on why the destructor is running. If it's running due to executing leaving the block normally, then the exception propagates outward. But if it's running due to unwinding as a result of some other exception, then that's a std::.
The dangerous parts are the first two cases, because those result in the exception being thrown (and possibly caught elsewhere) without the cleanup action ever taking place.
WIL addresses this problem by merely saying that if an exception occurs during copying/moving of the lambda, then the behavior is undefined.
C++ has a scope_ that is in the experimental stage, and it addresses the problem a different way: If an exception occurs during the construction of the capture, then the lambda is called before propagating the exception. (It can't do anything about exceptions during contruction of the lambda, and it also declares the behavior undefined if the lambda itself throws an exception.)
In practice, the problems with exceptions on construction or copy are immaterial because the lambda typically captures all values by reference ([&]), and those types of captures do not throw on construction or copy.
Post Updated on April 24, 2026 at 03:00PM
Thanks for reading
from devamazonaws.blogspot.com
Comments
Post a Comment