C++中delete的时候要小心incomplete class types

本文探讨了C++中删除不完整类型的行为及其潜在问题,特别是当试图删除仅声明而未定义的类实例时。文章提供了解决方案,并介绍了checked delete惯用法以避免此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缘起

The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be deleted with a delete-expression. When the class has a non-trivial destructor, or a class-specific operator delete, the behavior is undefined. Some compilers issue a warning when an incomplete type is deleted, but unfortunately, not all do, and programmers sometimes ignore or disable warnings.


In the following example, main.cpp can see the definition of Object. However, main() calls delete_object() -- defined in deleter.cpp -- whichdoes not see the definition of Object, but only forward declares it. Callingdelete on a partially defined type like this is undefined behavior which some compilers do not flag.

在VC++下,会有

Warning C4150

Deletion of pointer to incomplete type 'type'; no destructor called

在以一般情况下,如果我们只用到Object的指针,在特定平台下Object的指针大小固定,因此编译器不会报任何错误。然而,在调用delete来删除p的时候,编译器可以知道p所指的内存大小,因为内存分配器在内存块中保存了大小信息,可以正确释放p所占据的内存。但是,由于p是Incomplete Type,编译器无法知道A所对应的析构函数(destructor),因此不会调用p的析构函数。


////////////////////
// File: deleter.hpp
////////////////////
// declares but does not define Object
class 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);
}


解决办法


解决方法很简单,#include Object所在的头文件即可,如果忘记了#include,则会出现此Warning。


更彻底的方法是checked delete idiom。

The checked delete idiom relies on calls to a function template to delete memory, rather than calls todelete, which fails for declared but undefined types.

The following is the implementation of boost::checked_delete, a function template in the Boost Utility library. It forces a compilation error by invoking thesizeof operator on the parameterizing type,T. IfT is declared but not defined, sizeof(T) will generate a compilation error or return zero, depending upon the compiler. Ifsizeof(T) returns zero, checked_delete triggers a compilation error by declaring an array with -1 elements. The array name istype_must_be_complete, which should appear in the error message in that case, helping to explain the mistake.

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);
    }
};

References

http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Checked_delete

http://blog.youkuaiyun.com/ATField/article/details/1516378



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值