【问题标题】:Can I have memory leaks if I'm not using new keyword?如果我不使用 new 关键字,我会出现内存泄漏吗?
【发布时间】:2019-01-23 22:06:40
【问题描述】:

我是这门语言的新手,我对内存泄漏有一个基本的疑问。 如果我不使用new 关键字,是否可能发生泄漏? (即在堆栈中有我的变量并使用像std::vector这样的数据容器)

我应该担心这个问题吗?

如果是这样的话,谁能给我一个在没有动态分配内存的情况下造成泄漏的例子吗?

【问题讨论】:

  • 基本上,“不”。
  • 假设你也意味着你没有使用malloc,呵呵
  • @Phil "没有动态分配内存"
  • @DeiDei "没有动态分配内存"
  • 描述了一种获取泄漏的方法here

标签: c++ memory-leaks


【解决方案1】:

即将我的变量放在堆栈中并使用像std::vector这样的数据容器

不,使用std::vector 或其他标准容器您不必担心。

谁能给我一个在没有动态分配内存的情况下造成泄漏的示例?

一个常见的错误是循环依赖智能指针的形式:

class Child;
class Parent {
     std::vector<std::shared_ptr<Child>> childs;
};

class Child {
     std::shared_ptr<Parent> parent;
};

由于共享指针的引用计数器永远不会降为零,因此这些实例永远不会被删除并导致内存泄漏。

可以在此处找到有关导致该问题的原因以及如何避免该问题的更多信息

【讨论】:

    【解决方案2】:

    我认为如果您不动态保留内存,则不可能泄漏内存。可能全局变量不会被释放,但我不会称之为内存泄漏。

    但是,动态保留内存的方法比使用关键字new 更多。

    例如,malloc 分配一个内存块。同样calloc 保留内存并将其归零。

    您的操作还可以为您提供管理内存的方法。例如,strdup 用于 Linux。

    您还可以使用智能指针并调用std::make_uniquestd::make_shared。两种方法都动态分配内存。

    对于std::unique_ptr,如果您调用release() 并忘记删除指针,您可能会泄漏。

     std::make_unique<int>(3).release(); // Memory leak
    

    对于std::shared_ptr,如果创建循环引用,您可能会泄漏。您可以找到更多信息here

    此外,当您使用静态变量时,析构函数不会在变量超出范围时调用,而是在执行结束时调用。这并不完全是内存泄漏,因为最终调用了析构函数,但您可能分配了一些内存但未使用。

    例如,考虑以下代码:

    #include <iostream>
    #include <string>
    #include <vector>
    
    void f() 
    {
        static std::vector<int> v;
        v.insert(v.begin(), 100*1024*1024, 0);
        v.clear();
    }
    
    int main()
    {
        f();
        return 0;
    }
    

    std::vector::clear() 不需要释放向量分配的内存。因此,在调用f() 之后,您将分配 400 MB 的内存,但只能在 f() 内部访问。不完全是内存泄漏,而是分配的资源,直到结束才会自动释放。

    【讨论】:

    • 非常好。谢谢你的例子。特别是最后一个我认为我可能犯了那个错误!
    • 拥有静态向量并没有错。这不是一个特别好的答案。
    • @Neil 有一个静态向量是可以的。但是,如果你只推送元素而不弹出它们,它只会增长并且永远不会被删除。
    • @J.Calleja 析构函数将在程序正常退出时被调用。
    • 你是对的。最后调用析构函数。这是一个实际示例的简化,我们创建了一个静态向量并使其增长直到​​内存耗尽。我会更新答案。
    【解决方案3】:

    除了其他答案之外,内存泄漏的一个简单来源是外部库。其中很多,尤其是 C 或类似 C 的库,具有像 create_*destroy_* 这样的函数用于它们的数据类型。即使您从未显式调用new,仍然很容易发生内存泄漏。

    【讨论】:

    • 我个人为避免这个问题的建议是将类型包装在一个简单的 RAII 类中,或者使用带有自定义删除器的 std::unique_ptr
    猜你喜欢
    • 2019-02-03
    • 1970-01-01
    • 2014-12-26
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    相关资源
    最近更新 更多