在函数中留下指针会导致内存泄漏吗?

Posted

技术标签:

【中文标题】在函数中留下指针会导致内存泄漏吗?【英文标题】:does leaving pointers in functions cause memory leaks? 【发布时间】:2016-03-16 07:41:58 【问题描述】:

假设我有一个函数或类维护一些指向其他数据对象的指针,如下所示:

class MyObject 
    ...
    AnotherObject* o1, *o2;
    SomeObject* s1, *s2;
    ...


int main() 
    ...
    MyObject mo1 = new MyObject();
    ... // do stuff with mo1
    delete mo1;

假设它们在初始化期间/之后从其他地方分配了有效的指针值。

当我在内部分配这些指针后销毁 MyObject 对象时,如果我在销毁期间不将指针设为空,是否会导致内存泄漏?:

MyObject::~MyObject() 
    o1 = nullptr;
    o2 = nullptr;
    ...

谢谢。

【问题讨论】:

只要每个new 都与delete 配对,是否清空指针对象并没有什么区别。只要您不尝试使用它们,您就会得到不同类型的错误。 你应该发布整个MyObject类,否则很难说。 如果你使用new(或new[])但没有对应的delete(或delete[]那么你有内存泄漏。仅具有非空指针不会导致泄漏。然而,有一种更简单的方法可以避免内存泄漏:不要自己使用指针或动态分配。尽可能使用standard containers 或std::string 和RAII,不会有任何泄漏。 当你不执行三规则并且不使用 std::shared_ptr 时,有很多方法可以让你的腿断了。所以不要那样做,伤害会更小。 【参考方案1】:

不,它不会导致内存泄漏。但是请注意:

MyObject mo1 = new MyObject();
// do stuff with mo1
delete mo1;

如果do stuff with mo1 抛出异常(如果它包含对nullptr 的引用,则可能是这种情况)将导致内存泄漏。因此,建议不要像您那样使用裸指针,而是使用智能指针——这样 RAII 可以保证您的指针将被删除。

【讨论】:

谢谢!当我写这个问题时,我并不担心do stuff with mo1 会做什么,但无论如何它绝对值得考虑!【参考方案2】:

听起来您来自 Java 背景,需要将指针设置为 null 以允许垃圾收集器回收其他对象。如果是这样,答案很简单:不,这不是它在 C++ 中的工作方式。将指针设置为 null 对内存使用没有任何影响,并且无论如何都没有可以回收任何内存的垃圾收集器。

相反,您应该考虑所有权。大多数对象都有一个特定的所有者;一旦该所有者被删除,其拥有的对象也会被删除。这最方便地使用 unique_ptr 而不是原始指针建模。对于拥有更复杂所有权的对象,有 shared_ptr 和 weak_ptr。

再一次,没有垃圾收集器,所以任何时候你使用new创建一个对象,不知何故,某处必须有一个对应的delete。确保不会忘记此类删除的最简单方法是使用 unique_ptr。

还要警惕过于频繁地使用new。您的mo1 对象可以毫无问题地分配到堆栈上:它的生命周期仅限于一个函数(main),所以为什么不使用简单地将其分配为MyObject mo1; - 就足够了,无需新建或删除任何东西。

【讨论】:

【参考方案3】:

不,它不会。内存泄漏的发生是因为使用new 分配的未删除内存。清空指针只是以后检查它是否被删除的一种方式,它与内存泄漏无关。

另一方面,手动处理内存并不是实现您想要的最佳方式。存在智能指针(std::shared_ptrstd::unique_ptr...)。你应该看看他们。

【讨论】:

以上是关于在函数中留下指针会导致内存泄漏吗?的主要内容,如果未能解决你的问题,请参考以下文章

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

在静态方法中使用匿名 Lamba 订阅事件会导致内存泄漏吗?

这种对共享指针向量的回退是不是会导致内存泄漏?

这个 JavaScript 代码会导致内存泄漏吗?

在 Handler 线程的队列中添加匿名可运行对象会导致内存泄漏吗?

存储过程会导致内存泄漏吗?