Memory Pool 구현한 코드들이 꽤 많지만,
그중에서 제가 보고 있는 것은 Loki 의 SmallObject 입니다.
책으로 (Modern C++ design) 설명도 자세히 되어있고 해서 가벼운 마음으로 가져다 사용했는데...
이게 생각지도 못한 문제들이 많이 있더군요...
게다가 처음에는 Loki::SmallObject 에 버그가 있어서... 그거 잡느라 몇일 날리고...;;
지금 당면한 문제는 메모리 메니져가 singleton 으로 사용되고 있는데요.
전역으로 선언된 클래스가 메모리 메니져로 부터 메모리를 할당 받아서 사용하고 있다가
프로그램이 종료되는 순간에 메모리 메니져 보다 나중에 죽는 경우가 있어서 문제가 되고 있습니다.
코드로 설명하면 이렇습니다.
Code: Select all
class cMyClass
{
int * pVal;
public:
cMyClass() { pVal = MyMemoryPoolManager::new int; }
virtual ~cMyClass() { MyMemoryPoolManager::delete pVal; }
};
static cMyClass s_myVal;
~cMyClass() 가 호출되면 MyMemoryPoolManager::delete 가 비정상적으로 동작한다는 것이죠...
해결 방법을 여러가지 생각해 냈는데요..... Loki 개발자 분들과 이야기를 나누어 보고는... 쓸 수 있는 방법은 static 으로 클래스를 생성시키지 말아야 한다는 결론 밖에 내지 못했습니다.
현재 Loki::SmallObject 의 LifetimePolicy 는 Loki::NoDestroy 인데, 이것은 소멸자 호출이나 메모리 해제를 아에 한지 않는 방식입니다.
그러니까 이렇게 하면 static/전역 변수들이 다 죽어 나간 뒤에도 끝까지 살아 남는 것이죠.
그리고나서, 메모리는 (말하자면) leak 상태로 처리되고 OS 에 의해 최종 해지 되도록 하는 것입니다.
근데, 클라이언트 프로그래머 분들은 눈치 채셨겠지만, Win9X 에서는 이런식으로 게임 클라이언트를 종료 시키게 되면, 메모리 관리에 애로 사항이 만개 한다는 사실을 아실겁니다..
그래서 Loki::NoDestroy 는 사용할 수 없고, Loki::PhoenixPolicy 가 가능성이 높다고 생각하고 코드를 수정해서 돌려봤더니... 이것도 역시 심각한 문제가 발생하더군요...
(이 문제를 설명하려면 길어지는데, 간단히 말하면, 메모리 메니져가 죽으면서 자신이 예전에 할당해 줬던 메모리들을 모두 한꺼번에 해지 해버리고 죽는데, 그 뒤에 전역 변수의 소멸자가 수행되는 과정에서 이미 해지된 메모리들을 가지고 뭔가 작업을 하다가 access violation 예외가 뜬다는 겁니다)
그래서 결국 Loki::SingletonWithLongenvity 를 쓸 수 밖에 없게 되었고,
그 말은 즉, static/전역을 모두 Singleton 으로 바꾸어서 소멸되는 순서를 정해주어야 한다는 것입니다...
그래서 이 부분을 오늘 작업하던 중이었는데
모든 static 변수를 Singleton 으로 바꾸는 작업이 단순한게 아니더군요...;
앞에서 설명한 문제점은 비단 Loki 에만 있는 문제가 아니라는 걸 아실겁니다..
모든 종류의 메모리 관리자는 항상 자신으로 부터 할당 받은 메모리를 사용하는 녀석들 보다 나중에 죽지 않으면 안됩니다.
즉 전역으로 선언된 녀석이 메모리 관리자로부터 메모리를 받아서 사용하는 경우라면 Loki 만이 아니라 모든 메모리 관리자에 문제가 있을 수 있지요...
(OS 를 믿고 맏길 수 있는 서버 프로그래밍 같으면 문제가 안되겠지만...)
사실, 이거는 메모리 메니져 문제가 아니라 싱글톤 문제입니다.
다른 분들은 이런 문제를 어떻게 해결 하셨는지 궁금합니다....
*PS : 앞에서 설명한 내용들은 다음 주소에서 보실 수 있습니다.
http://sourceforge.net/tracker/index.ph ... tid=396644
맨 아랫쪽 부터 위로 올라가면서 읽어야 합니다. 시간 순서가 그렇습니다...