2012-05-13 1 views
4

싱글 톤 디자인 패턴을 구현하는 클래스가 있습니다. 나는 어떤 사람들은 그에게 좋은 아이디어를 생각하지 않는다 알고 있지만, 어쨌든 많은,싱글 톤을 사용할 때 메모리 누수가 발생했습니다.

을하는 데 도움이 - 나는 메모리 누수가 및 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.

==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; 
}; 

및 구현 : 여기에 내가 관리자 생성 코드의 여기 Valgrind의의 출력

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

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

"이제 Manager의 소멸자에서 바보 루프를 만들기 때문에 명시 적으로 삭제할 수 없습니다." 그게 무슨 뜻이야? –

+0

은 Manager의 인스턴스를 만들고 파괴하는 방법을 보여줍니다. – Zuljin

+0

포인터로 처리하지 마십시오. 훨씬 잘 작동합니다. http://stackoverflow.com/a/1008289/14065 gcc에서 쓰레드에 안전합니다 (링크 된 질문에있는 주석을보십시오). 포인터를 사용한다고해도 결코 포인터를 반환해서는 안되며, 그렇지 않으면 호출자는 객체를 삭제해야하는지 모릅니다. –

답변

4

C++에서 싱글 톤을 구현하는 일반적인 방법 중 하나는 클래스 정적 변수가 아닌 인스턴스 getter 내에 인스턴스를 function-static std::unique_ptr<T>으로 만드는 것입니다. 이렇게하면 프로그램이 완료되면 소멸자 호출이 보장되고 다형성으로 액세스되는 인스턴스를 만들 수 있습니다. 추상 기본 클래스에 대한 포인터를 통해.

Scott Meyers는이 주제에 대한 좋은 토론을 his "More Effective C++" book에 제공했습니다.

+0

소멸자를 명시 적으로 호출 할 때이 문제가 발생하지 않는다고 생각합니다. – yotamoo

+0

@yotamoo 멀티 스레드 환경에서 사용하지 않습니까? 왜냐하면 두 개의 쓰레드가 동시에 인스턴스를 얻으려고하면, 그들 중 하나가'Manager'를 누설하게됩니다. – dasblinkenlight

+0

@ dasblinkenlight 올바른 우려이지만, 이것을 일관되게 재현 한 것을 보면 아주 이상 할 것입니다. – KillianDS

2

Manager 확인을 정적 객체, 그리고 그것의 생성자 소멸자가 자동으로 호출됩니다. 또는 연산자 new로 할당해야하는 경우 스마트 포인터 (가능한 경우 unique_ptr, 그렇지 않으면 auto_ptr)에 포인터를 놓으면 포인터가 파괴 될 수 있도록 스마트 포인터에 넣습니다.

+1

좋은 답변은 정적 변수를 만들 때 싱글 톤이 어떤 전역 변수의 초기화에 사용된다면 전역 생성 순서에 대해 걱정할 필요가 있습니다. 따라서 Meyers 싱글 톤처럼 "인스턴스()"함수에있을 수 있습니다. 첫 번째 함수는 강제 초기화를 사용하므로 순서가 보장됩니다. –

+0

따라서 "연산자를 새 연산자로 할당해야하는 경우"생성 순서에 따라 비트 종속성이 생성자 인수와 동형입니다. –