为什么会导致内存泄漏?

时间:2014-07-10 18:40:15

标签: c++ memory-leaks

说我有一个AbstractBaseClass和一个ConcreteSubclass

以下代码创建了ConcreteSubclass,然后完全处理它并且没有内存泄漏:

ConcreteSubclass *test = new ConcreteSubclass(args...);
delete test;

但是,只要我将此指针推入向量,就会出现内存泄漏:

std::vector<AbstractBaseClass*> arr;
arr.push_back(new ConcreteSubclass(args...));
delete arr[0];

delete arr[0];的内存泄漏比没有删除的内存泄漏少,但仍有一些内存泄露。

我做了大量的在线查看,这似乎是一个很好理解的问题 - 我正在删除指向内存的指针,但不是实际的内存本身。所以我尝试了一个基本的解引用... delete *arr[0];,但这只是一个编译错误。我还尝试了一大堆其他引用和解引用,但每个只是给出编译器错误或程序崩溃。我只是没有找到正确的解决方案。

现在,我可以使用shared_ptr来完成工作而没有泄漏就好了(因为我没有C ++ 11可以提升):

std::vector<boost::shared_ptr<AbstractBaseClass>> arr2;
arr2.push_back(boost::shared_ptr<AbstractBaseClass>(new ConcreteSubclass(args...)));

但是我无法使用手动方法。这不是很重要 - 使用Boost非常容易,但我真的想知道我做错了什么,所以我可以从中学习,而不仅仅是在没有发现错误的情况下移动。

我尝试通过Boost的shared_ptr模板进行跟踪,但是我不断迷失,因为每个函数都有这么多的重载,而且我发现很难跟踪每个分支。

我认为就是这个:

template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
{
    boost::detail::sp_pointer_construct( this, p, pn );
}

但我一直在checked_array_delete结束,但这可能不正确,因为它使用delete[]。我需要深入了解

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

那只是打电话给delete,没什么特别的。试图贯穿所有参考和解除引用操作符从一开始就是一场灾难。所以基本上我被卡住了,我无法弄清楚Boost是如何使它工作的,而我的代码却没有。所以回到开头,如何重新编写此代码以使删除不泄漏?

std::vector<AbstractBaseClass*> arr;
arr.push_back(new ConcreteSubclass(args...));
delete arr[0];

谢谢。

1 个答案:

答案 0 :(得分:3)

shared_ptr存储&#34;删除&#34;,一个辅助函数 1 ,在调用{{{{}}之前将指针强制转换回原始类型(ConcreteSubclass*) 1}}。你还没有做到这一点。

如果delete有一个虚拟析构函数,那么调用AbstractBaseClass就可以了,并且与delete arr[0];一样好用。如果它没有,那么通过基础子对象的删除是未定义的行为,并且可能导致比内存泄漏更糟糕的事情发生。

经验法则:每个抽象基类都应该有一个用户声明的(显式默认为ok)析构函数

  • delete (ConcreteSubclass*)arr[0];

OR

  • virtual辅助功能修改

或两者兼而有之。


1 您已找到实施,它是protected:。但它使用checked_delete - new的返回类型进行实例化。所以它使用普通的删除,但是在指向类型checked_delete<ConcreteSubclass>(ConcreteSubclass* x)的指针上,即使没有虚拟调度的帮助,编译器也可以找到正确的析构函数。