In my destructor, I have to clean up a few resources. Let say I have three calls to clear resources that could throw. Since it is not good for letting an exception to leave a destructor, what should be my design pattern? Apparently the way below is not scalable.
Thanks.
class B::~B(){
try{
clearResourceA()
}
catch{
try{
clearResourceB();
}
catch{
clearResourceC();
}
clearResourceC();
}
clearResourceB();
.
.
}
Why not:
try{clearResourceA();} catch(...){}
try{clearResourceB();} catch(...){}
try{clearResourceC();} catch(...){}
Encapsulate each resource in a class which clears them in its destructor (with a surrounding try/catch):
struct ProperlyManagedA {
// some means of using the resource - a rudimentary way is this:
A &getA() { return a; }
const A &getA() const { return a; }
// cleanup
~ProperlyManagedA() {
try {
a.clear(); // whatever it is ClearResourceA actually does
} catch (...) {}
}
private:
A a;
}
A shared_ptr
with a custom deleter is one way to achieve this without having to create a whole class for each type of resource.
You might improve on discarding the exception (log the problem, for example), depending what's thrown.
Even better, modify resources A, B and C so that they clear themselves in their own destructors. That might not be possible, though.
Either way, you can then put as many such resources in a single class as you like, without adding any code to the destructor of the class. This is "scalability". The whole point of RAII, is that each user of a resource shouldn't have to write cleanup code in order to use the resource correctly.
Capture anything that can throw in your destructor with a catch-all (i.e., catch (...)) and do your best to handle the exceptions thrown. Make sure that no exceptions propagate out of the destructor, which the catch-all will help you prevent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With