메모내용

언리얼 엔진 메모리 관리

c++ 언어 메모리 관리의 문제점

C++ 이후에 나온 언어 JAVA / C# 은 이런 고질적인 문제를 해결하기 위해 포인터를 버리고
가비지 컬렉션 시스템을 도입했다.

가비지 컬렉션 시스템

언리얼 엔진의 가비지 컬렉션 시스템

언리얼 오브젝트가 대상이다. 일반 c++ 를 논하는 시스템이 아니다. 언리얼 오브젝트의 메모리를 관리하고, 일반 C++ 안에 선언된 언리얼 오브젝트의 관리를 하는 방법이다.

가지비 컬렉션을 위한 객체 저장소

가비지 컬렉터는 GUObjectArray 에 있는 플래그를 확인해 빠르게 회수해야할 오브젝트를 파악하고 메모리에서 제거한다

가비지 컬렉터를 사용해서 얻는 장점

언리얼 오브젝트를 통한 포인터 문제의 해결

언리얼 오브젝트의 유효성을 판단하는 방법

UObject* UObject 의 유효성을 판단하는 방법

nullptr 만 보고 유효하다고 판단해서는 안된다

  1. nullptr != UObject
    • 널포인터 인지 확인하기, 하지만 Dangling 문제까지 잡아 낼 순 없다.
  2. UObject->IsValid()
    • GC 에 의한 Pending Kill 상태까지 잡아낼 수 있다고 한다
  3. UObject->IsValidLowLevel()
    • 좀더 깊숙하게 검사하여 유효성을 판단하는 함수

가비지 컬렉터의 메모리 회수

한번 생성된 언리얼 오브젝트는 바로 삭제가 불가능하다

삭제하려고 delete 를 호출해서 삭제 시키려고 하면 안된다. 가비지 컬렉터를 기다려야 한다. ( 참조를 끊어 내는 방식을 활용해야 한다. )

가비지 컬렉터의 메모리 회수에서 제외하는법

가비지 컬렉터는 UPROPERTY 를 붙이지 않아 참조되지 않거나, 루트셋으로 지정되지 않거나, AddReferencedObjects 함수로 호출로 참조를 설정하지 않은 모든 언리얼 오브젝트를 회수합니다. 가비지 컬렉터가 참고하는 참조 등록의 기준가비지 컬렉터에게 알렸는가 이다. (가비지 컬렉터가 참고하는 주요 플래그를 통해서 , Garbage 플래그, RootSet 플래그) 내가 포인터로서 참조하고 있는가는 상관하지 않는다. 그래서, UPROPERTY() 붙여주거나, AddReferencedObjects 함수호출해주거나, 루트셋을 지정하는등으로 가비지 컬렉터에게 알리는것이 중요하다

오브젝트 선언의 기본 원칙

오브젝트 포인터는 가급적 UPROPERTY 로 선언하고 메모리는 가비지 컬렉터가 자동으로 관리하도록 위임한다.

루트셋(RootSet) 플래그의 설정

굉장히 중요해서 시스템이 시작해서 계속해서 살아있어야 하는 경우. 이러한 경우 Root Set 으로 설정해야 한다.

콘텐츠 관련 오브젝트에 루트셋을 설정하는 방법은 권장되지 않는다.

일반 클래스에서 언리얼 오브젝트를 관리하는 경우

                    
                        #pragma onece
                        #include "CoreMinimal.h"

                        /** 언리얼 오브젝트를 관리하는  비언리얼 클래스 */
                        class UNREALPROJECT_API FMyClass : public FGCObject
                        {
                        public:
                            FMyClass();

                            ~FMyClass();

                            TObjectPtr<UObject> UObject; // 언리얼 오브젝트
                        public:

                            // 언리얼 오브젝트 관리를 위해 구현해주어야할 함수 1
                            virtual void AddReferencedObjects(FReferenceCollector& Collector) override;

                            // 언리얼 오브젝트 관리를 위해 구현해주어야할 함수 2
                            virtual FString GetReferencerName() const override
                            {
                                return TEXT("FMyClass"); // 그냥 식별할수 있는 클래스이름을 적어주면된다.
                            }
                        }
                    
                

.cpp

                    
                        #include "MyClass.h"
                        
                        FMyClass::FMyClass()
                        {
                            UObject = NewObject<UObject>();
                        }

                        void FMyClass::AddReferencedObjects(FReferenceCollector& Collector)
                        {
                            if(UObject->IsValidLowLevel())
                            {
                                Collector.AddReferenceObject(UObject);
                            }
                        }
                    
                

언리얼 오브젝트의 관리 원칙