【问题标题】:Why is there a memory leak in the following C++ code?为什么以下 C++ 代码中存在内存泄漏?
【发布时间】:2020-05-28 16:54:12
【问题描述】:

假设存在一个名为 Vec 的类,它的唯一成员是一个名为 arr 的向量。以下代码不会泄漏内存。 (这意味着我的 Vec 析构函数按预期工作。)

int main() {
    Vec *obj = new Vec(5); // initializes a vector of size 5
    delete obj;
}

但是,在以下代码中,存在内存泄漏。但为什么?对于new 的每次使用,我似乎都有一个delete。我错过了什么?

int main() {
    Vec* obj;
    obj = new Vec(5);

    if (true) {
        delete obj;
        Vec* obj = new Vec(6);
    }

    delete obj;
}

PS:我使用 valgrind 检查了内存泄漏。

【问题讨论】:

    标签: c++ c++11 memory-leaks


    【解决方案1】:

    范围。

    Vec* obj = new Vec(6); 生成一个名为obj 的新变量,该变量仅存在于if 的主体中,并将​​obj 隐藏在外部范围内。内部obj 超出范围并在if 主体的末尾消失,并使用最后一个指向新分配的指针。然后代码在外部范围(not a good thing to do)处重新deletes obj。

    解决办法:

    int main() {
        Vec* obj;
        obj = new Vec(5);
    
        if (true) {
            delete obj;
            obj = new Vec(6); // re-uses the original obj
        }
    
        delete obj;
    }
    

    【讨论】:

    • "将最后一个指向新分配的指针" - 但是,如果我在最后一个delete obj; 之前执行cout << obj->arr.size();,我会得到6。这是为什么?为什么我要取回范围之外的阴影变量的属性?
    • @babrar 因为取消引用悬空指针时的行为未定义。在这种情况下,实现很可能恰好为两个 Vec 对象重复使用相同的内存。
    【解决方案2】:

    在 if 条件中声明的 Vec* obj 在另一个范围内。您在指向您在 main() 开头声明的 Vec* 对象的范围之外执行另一个删除操作。 因此,如果条件是您的内存泄漏,则在内部分配 Vec 数组

    【讨论】:

      【解决方案3】:

      当您再次说Vec* obj = 时,不再只是obj =,而是隐藏旧变量,而不是更新它。结果,您泄露了第二个obj,更糟糕的是,您双重释放了第一个。

      【讨论】:

        【解决方案4】:

        删除条件语句中的“Vec*”将修复内存泄漏。您正在条件内定义一个 Vec 类型的新指针(恰好也称为 obj),并且永远不会释放该内存。两个“删除”都引用了第一个“obj”,因为第二个“obj”超出了范围而没有在条件结束时被删除。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多