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

缘起

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.csdn.net/ATField/article/details/1516378



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误是因为对一个不完整的类进行了无效的使用。所谓不完整的类是指在声明该类的同时并没有完全定义,比如只是定义了类名而没有定义类的成员。这就导致编译器无法确定该类的大小和成员,从而无法正确地使用该类。要解决这个错误,需要在使用该类之前先完全定义该类的成员。 ### 回答2: "Invalid use of incomplete type class" 是一个常见的编译错误,在 C++ 编程的出现比较频繁。它的意思是对不完全类型的类进行无效的使用,这通常会导致编译错误。 C++ ,不完全类型是指由于各种原因而没有完全定义的类型。比如说,声明某个类的指针或引用,而该类的定义并没有在当前文件出现,那么此时就无法得知该类的大小和布局,进而无法决定指针或引用的大小和布局,编译器也就无法进行相应的内存分配和代码生成。这就是不完全类型的一个典型例子。 在不完全类型的类上进行一些错误的操作,比如试图直接创建该类型的对象、试图直接调用该类型的成员函数、试图访问该类型的成员变量等等,都会导致“invalid use of incomplete type class” 错误的发生。 为了解决这个问题,我们需要通过某种方式提供该不完全类型的类定义,使得编译器可以获取到相应的信息。具体来说,可以将该类的定义放在当前文件或者头文件,或者提前声明该类的定义等等。 总之,“invalid use of incomplete type class” 是一种编译错误,提示我们对不完全类型的类进行了错误的使用,需要根据实际情况及时提供相应的定义,以便编译器能够正确处理该类型。 ### 回答3: invalid use of incomplete type class是指在使用一个不完整的类的时候产生的错误。所谓不完整的类,就是指该类的声明已经定义,但其实现却尚未完整地编写出来。这种错误通常会在编译阶段被检测出来。 产生这种错误的原因有很多,最常见的是由于头文件之间的误用而导致的。当我们在一个头文件声明了一个类,但是却在实际使用这个类的地方没有包含这个头文件,或者包含的顺序不正确,就会出现invalid use of incomplete type class的错误。 还有一种原因是在类的定义使用了该类本身。比如我们在类的成员函数使用了该类的对象作为参数或者返回值,但是由于该类还没有完整定义,导致编译器无法确定该类的大小和内存布局,进而导致了该错误的出现。 为了解决这个问题,我们可以采用前向声明的方式来解决。前向声明可以理解为是告诉编译器这个类的存在,但是在这个地方并不需要知道具体的实现,只需要知道这个类的名称即可。通过这种方式,可以避免因为头文件引用的问题导致的编译错误。 总之,invalid use of incomplete type class是一个常见的编译错误,通常是由于头文件的引用问题导致的。但是通过前向声明的方式,我们可以很容易地解决这个问题,避免因为不必要的编译错误而浪费时间和精力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值