How to detect stack unwinding in a destructor

I have a simple C ++ object that I create at the beginning of the F () function to ensure that the two matched functions (OpDo, OpUndo) call F () at the beginning and return using the object constructor and destructor, However, I do not want the operation to be canceled if the exception was thrown inside the body of F (). Can this be done cleanly? I read about std :: uncaught-exception , but its use seems not to be recommended.

+6
c ++ stack stack-unwinding
source share
3 answers

Most people used std::uncaught_exception() to try to determine if debugging is waiting, so they can throw an exception from the destructor if it is not already there. This is usually considered not a good idea.

If you want to not cancel the operation, if an exception occurs, it should do the trick.

Remember that the destructor is your last chance to free any resources that the object has, because after the destructor completes, the object does not exist, and all remaining resources are now constantly leaking. If OpDo() allocates any memory files or files or something else, you need to deal with this in the destructor, no matter what.

+6
source share

Suppose your F returns some Helper class:

 Helper F() { MyClass doUndoWrapper; } 

When the flow is normal, an assistant is created. When an exception occurs, a copy of Helper is not created. Try using this semantics by placing Helper in the private constructor of the scope and declaring F as a friend - so no one could create an assistant.

 class Helper { private: friend Helper F(); Helper(){ //place there OpDo semantic - first entry // construct this class Helper(const Helper& copy){ //this must present to allow stack operations // copy constructor will be called at end of `F` to return value // so place OpUndo semantic there to mark success without exception 
0
source share

You can undermine the Idiom Scope Guard . Instead of not doing something in the destructor when an exception is not thrown, we invert this, but only do something if the exception is not thrown:

 class DoUndoRAII{ public: DoUndoRAII() : noexcept_(false) { // your stuff here } ~DoUndoRAII(){ if(noexcept_){ // do whatever you need to do } } void no_exception(){ noexcept_ = true; } private: bool noexcept_; }; void func(){ DoUndoRAII do_undo; // last line do_undo.no_exception(); } 

When an exception is thrown, do_undo.no_exception() will never be do_undo.no_exception() and thus will never set the value noexcept_ to true. :) An example can be found here on Ideone .

0
source share

All Articles