...
Object destructors are likely to be called during stack unwinding as a result of an exception being thrown. If the destructor itself throws an exception, having been called as the result of an exception being thrown, then the function std::terminate()
is called with the default effect of calling std::abort()
[ISO/IEC 14882-2014]. When std::abort()
is called, no further objects are destroyed, resulting in an indeterminate program state and undefined behavior. Do not terminate a destructor by throwing an exception.
...
Noncompliant Code Example (function-try-block)
This noncompliant code example, as well as the following compliant solution, presumes the existence of a Bad
class with a destructor that can throw. Although the class violates this rule, it is presumed that the class cannot be modified to comply with this rule.
...
Consequently, the caught exception will inevitably escape from the SomeClass
destructor because it is implicitly rethrown when control reaches the end of the function-try-block handler/.
Compliant Solution
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, or it should handle all exceptions and not rethrow them (even implicitly). This compliant solution differs from the previous noncompliant code example by having an explicit return
statement in the SomeClass
destructor. This statement prevents control from reaching the end of the exception handler. Consequently, this handler will catch the exception thrown by Bad::~Bad()
when bad_member
is destroyed. It will also catch any exceptions thrown within the compound statement of the function-try-block, but the SomeClass
destructor will not terminate by throwing an exception.
...
Attempting to throw exceptions from destructors or deallocation functions can result in undefined behavior, leading to resource leaks or denial-of-service attacks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL57-CPP | Low | Likely | Medium | P6 |
L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| destructor-without-noexcept delete-without-noexcept | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC++-DCL57 | |||||||
CodeSonar |
| LANG.STRUCT.EXCP.CATCH LANG.STRUCT.EXCP.THROW | Use of catch Use of throw | ||||||
Helix QAC |
| C++2045, C++2047, C++4032, C++4631 | |||||||
Klocwork |
| MISRA.DTOR.THROW | |||||||
LDRA tool suite |
| 453 S | Partially implemented | ||||||
Parasoft C/C++test |
| CERT_CPP-DCL57-a | Never allow an exception to be thrown from a destructor, deallocation, and swap | ||||||
Polyspace Bug Finder |
| CERT C++: DCL57-CPP | Checks for class destructors exiting with an exception (rule partially covered) | ||||||
PVS-Studio |
| V509, V1045 | |||||||
RuleChecker |
| destructor-without-noexcept delete-without-noexcept | Fully checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C++ Coding Standard | ERR55-CPP. Honor exception specifications ERR50-CPP. Do not abruptly terminate the program |
MISRA C++:2008 | Rule 15-5-1 (Required) |
Bibliography
[Henricson |
1997] | Recommendation 12.5, Do not let destructors called during stack unwinding throw exceptions |
[ISO/IEC 14882-2014] | Subclause 3.4.7.2, "Deallocation Functions" |
[Meyers |
2005] | Item 8, "Prevent Exceptions from Leaving Destructors" |
[Sutter |
2000] | "Never allow exceptions from escaping destructors or from an overloaded operator delete() " (p. 29) |
...
...