Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Noncompliant Code Example (function-try-block)

In this noncompliant code example, class SomeClass destructor attempts to handle exceptions thrown from the destructor of the bad_member subobject by absorbing them. However, the C++ Standard, [except.handle], paragraph 15 states in part [ISO/IEC 14882-2014], states in part:

The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.

Consequently, the caught exception will inevitably escape from the SomeClass destructor. Note that exceptions thrown from noncompliant destructors of class member objects or from base classes cannot be handled because they are implicitly rethrown when control reaches the end of the function-try-block handler, which is the only way to catch such exceptions.

Code Block
bgColor#FFcccc
langcpp
#include <stdexcept>
 
class SomeClass {
  class Bad {
    bool shouldThrow() const;
  public:
    ~Bad() noexcept(false) {
      if (shouldThrow()) {
        throw std::logic_error("Something bad");
      }
    }
  };

  Bad bad_member;

public:
  ~SomeClass()
  try {
    // ...
  } catch(...) {
    // Attempt to handle exceptions thrown from Bad destructor.
  }
}

Compliant Code Example (try-block)

A destructor should perform the same way whether or not there is an active exception. Typically, this means that it should invoke only operations that do not throw exceptions. If necessary, a try-block may be used if the destructor must invoke an operation that may throw an exception.

Code Block
bgColor#ccccff
langcpp
struct SomeClass {
  ~SomeClass()
    try { // function-try-block
      try {   // Ordinary try-block
        // Clean up
      } catch(...) {
        // Catch and handle exceptions thrown during cleanup
      }
    } catch(...) {
      // Catch and log exceptions thrown from non-compliantnoncompliant
      // Destructorsdestructors of member objects or base class subobjects

      // NOTE: Returning from a destructor function-try-block
      // causes the caught exception to be implicitly rethrown
    }
};

...

The compliant solution does not throw exceptions in the event the deallocation fails , but instead fails as gracefully as possible:

...

Bibliography

[ISO/IEC 14882-2014]

3.4.7.2, "Deallocation Functions"
15.2, "Constructors and Destructors"
15.3, "Handling an Exception"
15.4, "Exception Specifications"

[Meyers 05]Item 8, "Prevent exceptions from leaving destructors"
[Sutter 00]"Never allow exceptions from escaping destructors or from an overloaded operator delete()" (p. 29)
[Henricson 97]Recommendation 12.5, "Do not let destructors called during stack unwinding throw exceptions"

...