OOP52-CPP. 不要删除一个无虚析构的多态对象
原文链接:
OOP52-CPP. Do not delete a polymorphic object without a virtual destructor
C++ 标准, [expr.delete], 段 3 [ISO/IEC 14882-2014], 陈述如下:
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.
不要通过一个指向无virtual
析构函数的基类类型的指针来删除一个派生类对象。反而,应该定义带有虚构函数的基类。通过一个指向无visual
析构函数的基类类型的指针来删除一个派生类对象会导致 未定义行为,undefined behavior.
不兼容代码示例
在这个不兼容例子中,b
是一个多态指针类型,其静态类型是 Base *
,动态类型是 Derived *
。当 b
被删除时,它将导致 未定义行为,undefined behavior,因为 Base
没有 vritual
析构函数。 C++ 标准, [class.dtor], 段 4 [ISO/IEC 14882-2014], 陈述如下:
If a class has no user-declared destructor, a destructor is implicitly declared as defaulted. An implicitly declared destructor is an
inline public
member of its class.
隐式声明的析构函数不会被声明为 virtual
即使存在其他的 virtual
函数.
1 | struct Base { |
不兼容代码示例
在这个不兼容例子中,显式指针操作已经被替换为指针指针对象,演示了智能指针也遭遇了其他指针相同的问题。因为 std::unique_ptr
默认删除器对内部指针值调用了 delete
,后果和先前不兼容的示例一样。
1 |
|
兼容方案
在这个兼容方案中,Base
的析构函数是显式声明的 virtual
析构函数,确保多态删除操作结果是定义良好的行为。
1 | struct Base { |
例外
OOP52-CPP:EX0:允许删除一个无虚析构函数的多态对象,如果该对象是引用自指向该类的指针,而不是通过指向该类继承的类指针。
1 | class Base { |
注意假如 Derived
没有被标记成 final
,那么 delete this
可能实际上引用了一个 Derived
的子类,从而与该规则冲突。
OOP52-CPP:EX1:允许删除一个无虚析构函数的多态对象,如果它的基类有一个析构的 operator delete
,通过其他方式解决派生类的析构函数正确调用问题。
1 |
|
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 |
---|---|---|---|
Astrée | 20.10 | **non-virtual-public-destructor-in-non-final-class ** | Partially checked |
Axivion Bauhaus Suite | 7.2.0 | CertC++-OOP52 | |
Clang | 3.9 | -Wdelete-non-virtual-dtor |
|
CodeSonar | 6.2p0 | LANG.STRUCT.DNVD | delete with Non-Virtual Destructor |
Helix QAC | 2022.1 | C++3402, C++3403, C++3404 | |
Klocwork | 2022.1 | CL.MLK.VIRTUAL CWARN.DTOR.NONVIRT.DELETE | |
LDRA tool suite | 9.7.1 | 303 S** ** | Partially implemented |
Parasoft C/C++test | 2021.2 | CERT_CPP-OOP52-a | Define a virtual destructor in classes used as base classes which have virtual functions |
PRQA QA-C++ | 4.4 | 3402, 3403, 3404 | |
Polyspace Bug Finder | R2021b | CERT C++: OOP52-CPP | Checks for situations when a class has virtual functions but not a virtual destructor (rule partially covered) |
PVS-Studio | 7.17 | V599, V689 | |
RuleChecker | 20.10 | **non-virtual-public-destructor-in-non-final-class ** | Partially checked |
SonarQube C/C++ Plugin | 4.10 | 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” Subclause 12.4, “Destructors” |
---|---|
[Stroustrup 2006] | “Why Are Destructors Not Virtual by Default?” |
本文标题:OOP52-CPP. 不要删除一个无虚析构的多态对象
文章作者:xwnb
发布时间:2022-04-03
最后更新:2023-04-17
原始链接:https://xwnb.github.io/posts/4027020077/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留本声明。感谢您的阅读和支持!
分享