작성
·
41
0
ResourceManager::Clear() 에 해당하는 부분에 대해 질문이 있습니다.
ResourceManager이 싱글톤으로 만들어지고, Game의 소멸자에서 또 ResourceManager의 Clear을 호출함으로써, Clear을 총 두번 호출하게 됩니다.
이 때, ResourceManager::Clear 내부에 unordered_map에서 메모리 해제를 하기 위해 SAFE_DELETE을 사용하고 있는데, for문이 auto mesh로 값복사를 하여 호출하는데, 이러면 힙 메모리는 delete시켰지만, map에서 관리되고 있는 포인터는 아직 해당 주소를 가리키고있어 두번째 Clear에서 또 값을 복사해오고 주소값자체는 복사해오므로 if(ptr)도 통과한 상태로 delete을 다시한번 시도하여 오류를 내는것으로 보입니다.
근데 궁금한건, 왜 Game의 소멸자로 싱글톤의 Clear을 호출하는 것인지, 각 매니저의 생명주기를 RAII로 관리하게 하면 이런 이중 삭제를 고려안해도 되지 않나요?
또한, for문으로 참조로 SAFE_DELETE를 한다면, Clear두번 호출되어도 이중 삭제 방지되지만, 왜 map의 clear로 해당 상황을 방지하는 선택을 하셨는지 궁금합니다.
답변 1
0
Clear()는 여러 번 호출하더라도 안정성을 보장받을 수 있게 만들어주시고
그 외 부분은 정해진 규칙이 없어 원하시는 대로 하시면 됩니다.
다만 몇 가지 상황에 대한 답은 있는데요
[1] Game 소멸자에서 Clear()를 호출하는 이유
이 역시 필수는 아니고요.
사실 어차피 게임이 종료되는거라, 무시하고 해제를 안 해도 전혀 상관 없습니다.
일반적으로 리소스 매니저는 전체 Clear()를 하기 보단,
씬 이동이 필요할 때 기존의 리소스는 날리는 용도로 활용됩니다.
예를 들어 로비에서 활용하던 리소스는 인게임으로 들어가면 필요 없겠죠?
다만 일반적으로 처음 학습할 때는 #include <crtdbg.h>
~등을 활용해 메모리 누수가 없는지 추적하는 코드를 넣어놓는 경우가 많은데
Game 소멸자 등 어딘가에라도 매니저 Clear를 하지 않으면,
메모리 누수로 오인해 잡히는 경우가 생깁니다.
(메모리 누수를 추적하는 방식이 new 하면 등록하고 delete 하는지 체크하는 방식이라)
[2] 모든 매니저 생명주기를 RAII로 관리하면 좋지 않나
ResourceManager의 소멸자에 Clear() 넣는 것을 말씀하시는거라면
사실 [1]과 비슷한 이유로 어차피 프로그램이 종료되는
타이밍에 실행될 것이라 넣어도 그만 안 넣어도 그만입니다.
다만 역시 같은 이유로 메모리 추적 코드를 넣었을 때,
ResourceManager 소멸이 메모리 추적 코드가 발동하는 다음에 실행될 경우
이 또한 제대로 보장받지 못합니다.
결론적으로 그렇게 중요한 이유들이 있는 것은 아니고
이런 궁금증을 갖고, 언젠가 언리얼 엔진에서 어떻게 처리하는지 소스코드를 살펴보시면 됩니다.