【问题标题】:C++ destructor memory leakC++ 析构函数内存泄漏
【发布时间】:2015-08-15 20:51:46
【问题描述】:

关于正确处理析构函数的相对简单的问题...

首先我有一个类似这样的课程:

class Foo {
public:
    ReleaseObjects() {
        for (std::map<size_t, Object*>::iterator iter = objects.begin(); iter != objects.end(); iter++) {
            delete (*iter).second;
        }
        objects.clear();
    }

private:
    std::map<size_t,Object*> objects;
}

所以该函数只是删除使用“new”创建的对象。问题是一个对象类:

class Bar : public Object {
public:
    Bar() {
        baz = new Baz();
    }

    ~Bar() { delete baz; }
private:
    Baz* baz;
}

如果我将 Baz 类型对象添加到 Foo,然后尝试 ReleaseObjects(),则会出现内存泄漏 (valgrind)。问题指向 baz 被泄露,我猜这意味着 bar 中的析构函数永远不会被调用?所以我想知道的是如何在试图销毁该对象时调用 Bar 析构函数(我不能改变 Bar 类,但我可以改变 Foo)。

编辑: 糟糕,抱歉语法错误。无论如何,感谢所有回复,愚蠢的我忘了在我的 Baz 类中实现一个适当的析构函数!哦,Baz 实际上是一个模板类,但我认为 Baz 与我的问题有点无关,问题是 Bar 中的析构函数没有被调用......好吧,我错了,问题毕竟在 Baz 中。但再次感谢,我想我从这里弄明白了!

【问题讨论】:

  • Object 中的析构函数是虚拟的吗?也发布 Object 类
  • 这段代码没有泄露。这段代码甚至没有编译。请发布实际代码。
  • 你可以为 Baz 发布课程(或其他课程)吗?
  • 请发布一个最小的、完整的程序来演示错误。请参阅sscce.org 了解更多信息。
  • 你得到什么具体错误?您是将 Baz 添加到 Foo 中,还是将 Bar 添加到 Foo 的地图中? "delete (*iter).second 应该正确触发 Bar 的析构函数。

标签: c++ memory-leaks destructor delete-operator


【解决方案1】:

您必须确保您的析构函数是虚拟的,以便调用正确的派生析构函数。

class Object {
 . . .
 virtual ~Object()
 . . .
};

【讨论】:

  • 这几乎是我忘记实现的!而且我认为我的问题完全是另外一回事......谢谢!
【解决方案2】:

我不完全了解您的情况,但since you've got public inheritance, you probably want virtual destructors。特别是基类(Object)需要一个虚析构函数。

请注意,您给定的代码无法编译。 new 运算符返回一个指针,所以baz 必须是一个指针。

【讨论】:

    【解决方案3】:

    您应该始终使用智能指针。这些类型的行为类似于指针,但会自动释放内存,并且不需要任何此类函数。它们避免了各种令人讨厌的错误——可能包括这个错误,如果你使用 shared_ptr&lt;Bar&gt; 并把它扔掉的话。

    如果您想用 C++ 编写重要的软件,您必须了解并理解智能指针。

    【讨论】:

    • 如果问题是非虚拟析构函数,我认为 shared_ptr 不会起作用。 (虽然不是 100% 确定)
    • @MooingDuck:它对析构函数使用类型擦除,因此如果您从 Bar 开始,避免此问题。
    猜你喜欢
    • 2013-11-28
    • 2012-09-02
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    相关资源
    最近更新 更多