2012-05-13 3 views
4

У меня есть класс, в котором я реализую шаблон дизайна singelton. Я знаю, что некоторые люди не думаю, что его хорошая идея, но это очень помогает,Утечка памяти при использовании singleton

Во всяком случае - у меня есть утечка памяти и vlagrind указывает мне на эти строки:

_singleton = new Manager(); //Manager::instance() (Manager.cpp:18) 

И

Manager::Manager() : _file(new ofstream), _tasks(new map<int, Task *>()), 
     _idState(new map<int, int>()), _closing(false), _pending(false), 
     _lock(new pthread_mutex_t), _endLock(new pthread_mutex_t), _cond(new pthread_cond_t), 
     _flushCond(new map<int, pthread_cond_t *>()), _attr(new pthread_attr_t) { 
//The last line is line 25 in Manager::Manager 

Теперь в деструкторе менеджера я не могу явно удалить его, потому что он создает глупую петлю (поскольку деструктор будет вызываться при удалении _singleton, приводящем к бесконечному циклу). Как избавиться от этой утечки? Благодаря!

P.s. вот выход valgrind есть:

==17823== 512 bytes in 1 blocks are definitely lost in loss record 2 of 2 
==17823== at 0x4C27297: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==17823== by 0x40151E: Manager::Manager() (Manager.cpp:25) 
==17823== by 0x4014DB: Manager::instance() (Manager.cpp:18) 
==17823== by 0x406475: initdevice(char*) (outputdevice.cpp:66) 
==17823== by 0x4061D5: main (driver.cpp:21) 
==17823== 
==17823== LEAK SUMMARY: 
==17823== definitely lost: 512 bytes in 1 blocks 
= =17823== indirectly lost: 0 bytes in 0 blocks 
==17823==  possibly lost: 288 bytes in 1 blocks 
==17823== still reachable: 0 bytes in 0 blocks 
==17823==   suppressed: 0 bytes in 0 blocks 

Дополнение: вот код, где я создаю менеджер:

Manager.h: 
class Manager { 
public: 
    ~Manager(); 
    static Manager * instance(); 
private: 
    Manager(); 
    static Manager * _singleton; 
}; 

а реализация:

Manager.cpp: 
Manager * Manager::_singleton = 0; 

Manager * Manager::instance() { 
    if (!_singleton) 
     _singleton = new Manager(); 
    return _singleton; 
} 
+0

«Теперь в деструкторе менеджера я не могу явно удалить его, потому что он создает глупую петлю». - что это значит? –

+0

покажите нам, как вы создаете и уничтожаете экземпляр менеджера. – Zuljin

+0

Не делайте этого с указателями, и он работает намного лучше. http://stackoverflow.com/a/1008289/14065 Он даже становится потокобезопасным на gcc (см. примечания в связанном вопросе). Даже если вы используете указатели, вы никогда не должны возвращать указатель, вы должны вернуть ссылку из 'instance()' в противном случае вызывающий не уверен, что они должны удалить объект, и они никогда не должны. –

ответ

4

Один из распространенных способов реализации singleton в C++ делает экземпляр функцией-static std::unique_ptr<T> внутри экземпляра getter, а не статической переменной класса. Это обеспечивает вызов деструктора при завершении программы и позволяет создать экземпляр, доступ к которому получает доступ полиморфно, например. через указатель на абстрактный базовый класс.

Скотт Мейерс дал хорошее обсуждение этой темы в his "More Effective C++" book.

+0

Я не думаю, что это проблема, поскольку я вызываю деструктор явно – yotamoo

+0

@yotamoo Вы не используете его в многопоточной среде, не так ли? Потому что, если два потока попытаются получить экземпляр одновременно, один из них пропустит «Менеджер». – dasblinkenlight

+0

@dasblinkenlight Хотя это правильная проблема, было бы очень странно, если бы он увидел, что это воспроизводится последовательно. – KillianDS

2

Сделать Manager статический объект, и это конструктор и деструктор будет вызван автоматически. Или если вы должны выделить его с помощью оператора new, поместите его в интеллектуальный указатель (unique_ptr, если можете, иначе auto_ptr), чтобы он был уничтожен, когда указатель.

+1

Хороший ответ, за исключением того, что когда вы делаете переменную static, вам может понадобиться беспокоиться о глобальном порядке создания, если ваш singleton используется при инициализации любых глобальных переменных. Таким образом, хорошим местом для этого является, вероятно, функция «instance()», как это делает синглтон Meyers. Это гарантирует порядок, потому что первая функция использует инициализацию. –

+0

Таким образом, «если вы должны выделить его с помощью новых операторов» в порядке создания, они изоморфны аргументам конструктора. –

Смежные вопросы