...
In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
Do not destroy delete an object of derived class type through a pointer to its base class type that has a non-virtual
destructor. Instead, the base class should be defined with a virtual
destructor. Deleting an object through a pointer to a type without a virtual
destructor results in undefined behavior.
Noncompliant Code Example
In this noncompliant example, b
is a polymorphic pointer type whose static type is Base *
and whose dynamic type is Derived *
. When b
is destroyddeleted, it results in undefined behavior because Base
does not have a virtual
destructor. According to the C++ Standard, [class.dtor], paragraph 4 [ISO/IEC 14882-2014 ]:
...
Code Block | ||||
---|---|---|---|---|
| ||||
struct Base { virtual void f(); }; struct Derived : Base {}; void f() { Base *b = new Derived(); // ... delete b; } |
Compliant Solution
In this compliant solution, the destructor for Base
has an explicitly declared virtual
destructor, ensuring that the polymorphic destroy delete operation results in well-defined behavior. To guard against subclasses of Derived
not having access to a virtual
destructor, Derived
is marked as a final
class so that it cannot be further inherited from.
Code Block | ||||
---|---|---|---|---|
| ||||
struct Base { virtual ~Base() = default; virtual void f(); }; struct Derived final : Base {}; void f() { Base *b = new Derived(); // ... delete b; } |
Risk Assessment
Attempting to destruct a polymorphic object that does not have a virtual
destructor declared results in undefined behavior. In practice, potential consequences include abnormal program termination and memory leaks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
OOP52-CPP | Low | Likely | Low | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
| 2116, 3403 | ||||||||
Klocwork |
| CL.MLK.VIRTUAL | |||||||
Clang |
| -Wdelete-non-virtual-dtor | |||||||
LDRA tool suite |
| 303 S | Partially implemented | ||||||
Parasoft C/C++test | 9.5 | OOP-22 | |||||||
SonarQube C/C++ Plugin |
| S1235 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C++ Coding Standard | EXP51-CPP. Do not delete an array through a pointer of the incorrect type |
Bibliography
[ISO/IEC 14882-2014] | Subclause 5.3.5, "Delete" |
[Stroustrup 06] | "Why Are Destructors Not Virtual by Default?" |
...