唯一指针内存泄漏

Posted

技术标签:

【中文标题】唯一指针内存泄漏【英文标题】:unique pointer memory leak 【发布时间】:2016-08-04 00:08:28 【问题描述】:

我想知道是否有人可以帮助我解决我对唯一指针的一些困惑。考虑以下代码:

// some class "complex" defined here

int main()

    while(1) 
    
        unique_ptr<complex> p(new complex[256]);
        p.reset();
    
    return 1;

现在据我了解,当我在唯一指针上调用 reset() 时,它应该删除其原始指针所指的对象。在这种情况下,该对象恰好是创建的 256 个对象中的第一个 complex 类型的对象。因为这就是new complex[256] 所做的,对吗?它只是返回一个指向数组中第一个对象的指针(当然,它也创建)?所以剩下的 256 个对象应该保持不变。

按照这个逻辑,无限循环应该会造成内存泄漏,但这不会发生。我正在使用 MS Visual Studio 2013。

我错过了什么?如果有人能告诉我这里发生的事情并确认或反对我的猜想,我将不胜感激

【问题讨论】:

【参考方案1】:

当您的unique_ptr 超出范围时,它将在其拥有的指针上调用delete。因此,您使用delete 而不是delete[] 来删除new[] 分配的内存。这是未定义的行为,尝试进一步推理为什么您的代码没有按照您期望的方式运行几乎毫无意义。

但可能发生的情况是在该指针上调用 delete 意味着只有数组中的第一个 complex 对象被销毁(意味着它的析构函数被调用)。剩下的 255 个对象不会调用析构函数,但是整个数组占用的内存还是被释放了。

我认为您的期望是您的程序使用越来越多的内存并最终在new 分配失败时死掉,但是如果正在释放数组占用的内存,那将永远不会发生。


使用unique_ptr 处理数组的正确方法是使用数组类型的部分特化

unique_ptr<complex[]> p(new complex[256]);
//                ^^

或者如果你的标准库实现了std::make_unique (C++14),那么使用

auto p = std::make_unique<complex[]>(256);

【讨论】:

避免new 并使用make_unique 可以避免这种错误:auto p = std::make_unique&lt;complex[]&gt;(256); 如何在没有明确告知的情况下释放内存?那是编译器特定的功能吗?最后,考虑到它用于主模板,std::default_delete&lt;T&gt; 也用于数组专业化是否正确?非常感谢快速响应的家伙。 内存被明确告知要在unique_ptr 中释放。这不是编译器功能,只是类的实现方式。对于数组特化,T 应该读作complex[],所以std::default_delete&lt;T&gt; 将是delete[] 但问题是,我尝试使用常规原始指针重新创建上述代码。也就是说,complex* p = new complex[256]; delete p - 内存仍然被释放。所以我不能把它和这里的类实现联系起来。那么是谁在做这件事呢? :) 关于std::default_delete&lt;T&gt; - 你是对的,谢谢。有一个数组特化struct default_delete&lt;T[]&gt;unique_ptr&lt;T[], Deleter&gt; 唯一指针数组特化调用,就像@Praetorian 提到的那样 @MutomboDikey 我不明白你的困惑。 new 分配内存并构造对象,而delete 销毁对象并释放内存。类似地,数组版本将分别为这 N 个对象分配和构造 N 个对象并销毁和释放内存。忽略由于new[]delete 不匹配而导致的未定义行为,delete 正在销毁单个complex 对象并释放您分配的内存。由于 UB,不需要这样做,但您的实现可能仍然可以正确处理此问题。

以上是关于唯一指针内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

智能指针(解决你的内存泄漏)

智能指针(解决你的内存泄漏)

C语言中的指针和内存泄漏

将指针推回指针向量是不是存在内存泄漏?

查找由智能指针引起的内存泄漏

C++ 智能指针