跳转到内容

更多 C++ 惯用法/Checked delete

来自 Wikibooks,开放书籍,开放世界

Checked delete

[编辑 | 编辑源代码]

提高delete表达式的安全性。

也称为

[编辑 | 编辑源代码]

动机和示例代码

[编辑 | 编辑源代码]

C++ 标准允许在 5.3.5/5 中,使用 delete-expression 删除指向不完整类类型的指针。当类具有非平凡析构函数或类特定的 operator delete 时,行为是未定义的。一些编译器在删除不完整类型时会发出警告,但不幸的是,并非所有编译器都会这样做,并且程序员有时会忽略或禁用警告。

在以下示例中,main.cpp 可以看到 Object 的定义。但是,main() 调用在 deleter.cpp 中定义的 delete_object(),它没有看到 Object 的定义,而只是向前声明它。对像这样部分定义的类型调用 delete 是未定义的行为,一些编译器不会标记它。

////////////////////
// File: deleter.hpp
////////////////////
// Declares but does not define Object.
struct Object;
void delete_object(Object* p);

////////////////////
// File: deleter.cpp
////////////////////
#include "deleter.hpp"

// Deletes an Object without knowing its definition.
void delete_object(Object* p)
{
  delete p;
}

////////////////////
// File: object.hpp
////////////////////
struct Object
{
  // This user-defined destructor won't be called when delete is
  // called on a partially-defined (i.e., predeclared) Object.
  ~Object() {
     // ...
  }
};

////////////////////
// File: main.cpp
////////////////////
#include "deleter.hpp"
#include "object.hpp"

int main() {
  Object* p = new Object;
  delete_object(p);
}

解决方案和示例代码

[编辑 | 编辑源代码]

Checked Delete 惯用法依赖于对函数模板的调用来删除内存,该模板对于已声明但未定义的类型将失败,而不是对 delete 的调用。

以下是 Boost 效用库中的函数模板 boost::checked_delete 的实现。它通过对参数化类型 T 调用 sizeof 运算符来强制编译错误。如果 T 已声明但未定义,sizeof(T) 将生成编译错误或返回零,具体取决于编译器。如果 sizeof(T) 返回零,checked_delete 通过声明具有 -1 个元素的数组来触发编译错误。数组名称是 type_must_be_complete,在这种情况下,它应该出现在错误消息中,有助于解释错误。

template<class T> 
inline void checked_delete(T * x)
{
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete x;
}

template<class T> 
struct checked_deleter : std::unary_function <T *, void>
{
    void operator()(T * x) const
    {
        boost::checked_delete(x);
    }
};

注意:相同的技术也可以应用于数组删除运算符。

警告:std::auto_ptr 不使用任何等效于 checked delete 的东西。因此,如果在声明 auto_ptr 时,模板参数类型未完全定义,则使用不完整类型实例化 auto_ptr 可能会导致其析构函数中的未定义行为。

已知用途

[编辑 | 编辑源代码]
[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
华夏公益教科书