【问题标题】:Memory leak when deleting a singleton object, cpp删除单例对象时内存泄漏,cpp
【发布时间】:2012-05-15 07:53:54
【问题描述】:

我不知道为什么我会在这里出现内存泄漏,并且非常感谢任何建议。 请注意,在进程终止之前,我调用了 destroy(),这是一个静态成员函数,应该删除单例对象。

这是相关代码和valgrind的messaeg:

Manager.h:
class Manager {
public:
    // Constructor/destructor
    static Manager * instance();
    static void destroy();
    ~Manager();
        // Bunch of functions that I didn't write here

private:
    Manager();
    static Manager * _singleton; 
        // Bunch of fields that I didn't write here
};

Manager.cpp:
#include "Manager.h"

Manager * Manager::_singleton = NULL;

Manager * Manager::instance() {
    if (_singleton == NULL) {
            _singleton = new Manager();
        }
    return _singleton;
}

void Manager::destroy()
{
    delete _singleton;
    _singleton = NULL;
}

/*
 * Destructor
 */
Manager::~Manager() {
    // Deleting all fields here, memory leak is not from a field anyway
}

这是 valgrind 的报告:

==28688== HEAP SUMMARY:
==28688==     in use at exit: 512 bytes in 1 blocks
==28688==   total heap usage: 12 allocs, 11 frees, 10,376 bytes allocated
==28688== 
==28688== 512 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28688==    at 0x4C27297: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28688==    by 0x4014CE: Manager::Manager() (Manager.cpp:33)
==28688==    by 0x401437: Manager::instance() (Manager.cpp:15)
==28688==    by 0x4064E4: initdevice(char*) (outputdevice.cpp:69)
==28688==    by 0x406141: main (driver.cpp:21)
==28688== 
==28688== LEAK SUMMARY:
==28688==    definitely lost: 512 bytes in 1 blocks
==28688==    indirectly lost: 0 bytes in 0 blocks
==28688==      possibly lost: 0 bytes in 0 blocks
==28688==    still reachable: 0 bytes in 0 blocks
==28688==         suppressed: 0 bytes in 0 blocks

为什么会出现这种泄漏?我确实删除了destroy()中的_singleton

正如我所说,我将不胜感激,谢谢!

【问题讨论】:

  • 在调用 'destroy()' 之后,您会第二次调用 'instance()' 吗?在这种情况下,内存泄漏是可能的
  • 您将不得不发布一个小的可编译的简约代码示例来演示该问题。您发布的代码如果使用正确应该没有泄漏,但只有如果,除非我们看到代码,否则我们不知道。
  • 在销毁时,请检查_singleton是否为空,然后在destroy()方法中释放。
  • @undefined valgrind 如果有指向内存的指针,通常不会报告“肯定丢失”。而valgrind 报告泄漏是在构造函数中分配的内存,不是Managernew 中(尽管在这里很难知道——我认为一些编译器实际上可能在构造函数的新表达式中进行分配)。
  • @Als:哦!如果它是合法的,那么可以使用它。想想我们在 Windows 中处理“CloseHandle”API 的方式。

标签: c++ memory-leaks valgrind


【解决方案1】:

这里有几点需要注意。最明显的是:你什么时候 致电Manager::destroy。第二件事是内存valgrind 似乎在抱怨是在构造函数中分配的 Manager,你没有给我们看。如果我们可以相信错误信息 (我通常发现valgrind 在这方面是可靠的, 虽然它可以被愚弄),但没有剩余的指向内存的指针; 要么您没有删除对象中的字段之一,要么 对象在其构造函数中分配内存,它不会保存在 场地。

最后,最好不要销毁单例。 单例习语的全部目的是避免顺序 初始化问题(至少在 C++ 中——否则,只需声明 对象的静态实例就足够了)。破坏对象 引入了可能的破坏顺序问题。如果你不破坏 它,valgrind 将警告可能的内存泄漏(不是“绝对 lost");您可以忽略警告,也可以将其过滤掉。

【讨论】:

  • 如果我不删除 _singleton 我会在程序终止时发生内存泄漏
  • @yotamoo 在哪里?在非常真实的意义上,程序终止时不存在内存泄漏之类的事情。系统会自动恢复所有内存。内存泄漏是指程序使用的内存越来越多,运行的时间越长,实际上并不需要它使用的内存。
猜你喜欢
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 2015-02-12
  • 2011-01-26
  • 2016-06-11
  • 1970-01-01
相关资源
最近更新 更多