
C++标准,[expr.delete], 第3段 [ISO/IEC 14882-2014], 阐述如下:
在第一种替代情况下(删除对象),如果被删除对象的静态类型和其动态类型不同,
静态类型应当是被删除对象动态类型的基类,并且静态类型应当有虚析构函数,否则行为是未定义的。
在第二种替代情况下(删除数组),如果被删除对象的动态类型和其静态类型不同,其行为是未定义的。
不要通过和对象动态指针类型不同的静态指针类型来删除一个数组对象。
通过一个不正确类型的指针删除一个数组会导致未定义的行为。
在这个不符合规范的代码示例中,一个Derived类型的对象数组被创建,并通过Base*类型的指针被存储。
虽然Base::~Based()被声明为虚函数,但是它仍然会导致未定义的行为。
并且,通过静态类型Base*进行算术运算会违反规则 CTR56-CPP. Do not use pointer arithmetic on polymorphic objects。
struct Base {
virtual ~Base() = default;
};
struct Derived final : Base {};
void f() {
Base *b = new Derived[10];
// ...
delete [] b;
}
符合规范的解决方案
在这个符合规范的解决方案中,b的静态类型是Derived *,当通过下标访问数组和删除指针时不会导致未定义的行为。
struct Base {
virtual ~Base() = default;
};
struct Derived final : Base {};
void f() {
Derived *b = new Derived[10];
// ...
delete [] b;
}
风险评估
通过不正确的静态类型尝试销毁多态对象数组是未定义的行为。
在实践中,潜在的后果包括非正常的程序执行和内存泄漏。
| 规则 | 严重性 | 可能性 | 修复代价 | 优先级 | 等级 |
|---|---|---|---|---|---|
| EXP51-CPP | 低 | 不太可能 | 中 | P2 | L3 |
相关规则
| SEI CERT C++ Coding Standard | CTR56-CPP. Do not use pointer arithmetic on polymorphic objects |
| SEI CERT C++ Coding Standard | OOP52-CPP. Do not delete a polymorphic object without a virtual destructor |
参考书目
| ISO/IEC 14882-2014 | Subclause 5.3.5, “Delete” |
参考链接
EXP51-CPP. Do not delete an array through a pointer of the incorrect type

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。




近期评论