C++ 언어 메모리 관리의 문제점
- C++은 저수준으로 메모리 주소에 직접 접근하는 포인터를 사용해 오브젝트를 관리한다.
- 그러다보니 프로그래머가 직접 할다과 해지 짝 맞추기를 해야 한다.
- 이를 잘 지키지 못하는 경우 다양한 문제가 발생할 수 있다.
- 잘못된 포인터 사용 예시
- 메모리 누수(Leak) : new를 했는데 delete 짝을 맞추지 못함. 힙에 메모리가 그대로 남아있음.
- 허상(Dangling)포인터 : 이미 해제해 무효화된 오브젝트의 주소를 가리키는 포인터
- 와일드(Wild) 포인터 : 값이 초기화되지 않아 엉뚱한 주소를 가리키는 포인터.
- 잘못된 포인터 값은 다양한 문제를 일으키며, 한 번의 실수는 프로그램을 종료시킴.
- 게임 규모가 커지고 구조가 복잡해질수록 프로그래머가 실수할 확률은 크게 증가한다.
C++ 이후에 나온 언어 JAVA/C#은 이런 고질적인 문제를 해결하기 위해 포인터를 버리고 대신 가비지 컬렉션 시스템을 도입함.
가비지 컬렉션 시스템
언리얼 엔진의 가비지 컬렉션 시스템
- 마크-스윕 방식의 가비지 컬렉션 시스템을 자체적으로 구축함
- 지정된 주기마다 몰아서 없애도록 설정되어 있음. (기본 값 60초)
- 성능 향상을 위해 병렬 처리, 클러스터링과 같은 기능을 탑재.

가비지 컬렉션을 위한 객체 저장소
- 관리되는 모든 언리얼 오브젝트의 정보를 저장하는 전역 변수 : GUObjectArray
- GUObjectAttay의 각 요소에는 플래그가 설정되어 있음.
- 가비지 컬렉터가 참고하는 주요 플래그
- Garbage 플래그 : 다른 언리얼 오브젝트로부터의 참조가 없어 회수 예정인 오브젝트
- RootSet 플래그 : 다른 언리얼 오브젝트로부터 참조가 없어도 회수하지 않는 특별한 오브젝트
가비지 컬렉터의 메모리 회수
- 가비지 컬렉터는 지정된 시간에 따라 주기적으로 메모리를 회수한다.
- Garbage 플래그로 설저된 오브젝트를 파악하고 메모리를 아넌하게 회수함.
- Garbage 플래그는 수동으로 설정하는 것이 아닌, 시스템이 알아서 설정함.
루트셋 플래그의 설정
- AddToRoot 함수를 호출해 루트셋 플래그를 설정하면 최초 탐색 목록으로 설정됨
- 루트셋으로 설저된 언리얼 오브젝트는 메모리 회수로부터 보호받음.
- RemoveFromRoot 함수를 호출해 루트셋 플래그를 제거할 수 있음.
- 콘텐츠 관련 오브젝트에는 권장되지 않음.
언리얼 오브젝트의 관리 원칙
- 생성된 언리얼 오브젝트를 유지하기 위해 레퍼런스 참조 방법을 설계할 것
- 언리얼 오브젝트 내의 언리얼 오브젝트 : UPROPERTY 사용
- 일반 C++ 오브젝트 내의 언리얼 오브젝트 : FGCObject의 상속 후 구현
- AddReferencedObjects 함수 구현해야 함.
- 생성된 언리얼 오브젝트는 강제로 지우려 하지 말 것
- 참조를 끊는다는 생각으로 설계할 것
- 가비지 컬렉터에게 회수를 재촉할 수는 있음
- 콘텐츠 제작에서 Destroy함수를 사용할 수 있으나, 결국 내부 동작은 동일함.