언리얼의 메모리 관리 시스템은 Garbage Collection 구현을 위해 reflection을 사용함
(언리얼 프로퍼티 시스템 🪞언리얼 프로퍼티 (리플렉션) )
가비지 컬렉션 Garbage Collection
가비지 컬레션은 C++에서 제공하는 기능이 아니다.
그것이 C++의 장점인 직접 메모리 관리가 가능하다는 것과 연결점이 있다.
항상 일정한 실행과정과 결과를 가진다는 것
다만, 동시에 치명적인 단점인 실수를 통한 memory leak가 발생할 수 있다는 것이다.
무튼, Unreal은 이런 memory leak 방지를 위해 Garbage Collection을 제공한다.
(아래부터 GC로 줄여 작성하겠습니다)
언리얼에서의 GC
언리얼 프로퍼티 시스템.
즉, 리플렉션을 사용해 객체가 사용되고 있는지 알 수 있다.
그래서 이 obejct가 계속해서 필요한지, 아니면 삭제해도 되는지 결정
30~60초 단위로 “Root Set”를 검사한다.
이때, Root Set은 게임 내에 영구적으로 존재해야 하는 Object가 되는데,
이 Root Set을 통해 접근할 수 없는, 접근할 길이 없는
→ 즉 더 이상 사용되지 않는 instance가 무엇인지 확인한다.
이렇게 확인한 instance의 메모리 공간을 해제하여 null로 변경한다.
수동으로 메모리를 해제하고 싶다면,
object->Destroy();
이렇게 사용한다.
명심하자.
new, delete 구문은 Unreal Property 시스템이 인지할 수 없다.
따라서 Garbage Collection에 포함되지 않는다.
언리얼에서 GC를 위한 규칙
- 클래스의 모든 멤버변수는 UPROPERTY 매크로가 필요하다.“naked” 매크로가 없는 상태에서는 엔진이 변수를 인지하지 못함.
- 그래서 내가 삭제한 object의 pointing을 계속 남겨둘 수도 있다는 뜻.
- 클래스의 멤버 포인터는 UObject 또는 UObject에서 파생된 객체를 가리켜야 한다.
포인터로 관리하는 객체가 내가 임의로 설정한 class를 가리키면 안되고,class customClass{ // 어쩌구저쩌구 } // *** 중략 *** public: UPROPERTY() customClass* cc; // 이건 X UPROPERTY() UObject* MyUObject; // 이건 O
- UObject에서 파생된 클래스만 가능하다는 것.
- Non-UObject를 pointing하려면, engine 내에 “global”하게 존재하거나,
UObject 내부에 선언된 클래스여야 한다.
아니라면 GC에 의해 삭제될 수 있다.
- UObject(와 파생클래스)의 포인터를 안전하게 담을 수 있는 container는 TArray뿐
TArray만이 UObject와 파생 클래스들을 안전하게 저장할 수 있다.// TArray 선언 및 초기화 TArray<UObject*> ObjectArray; // MyClass 포인터를 TArray에 추가 UObject* NewObject = NewObject<UObject>(); ObjectArray.Add(NewObject);
어쨌든 가장 중요한 것은
1. Unreal에서 GC는 Reflection(Unreal Property)를 통해 동작함
- 요약.
-
💡결국 UPROPERTY나 UObject나 TArray처럼
reflection에 탐지되는 매크로 또는 형식을 사용해야 한다는 말
- 가비지 컬렉터는 무조건 reflection의 데이터에 의존한다!
- (아니라면 GC에 삭제될 수 있다는 뜻)
댓글 영역