GUObject에 전역을 의미하는 G가 붙음
언리얼 엔진이 활성화되면 누구나 GUObject에 접근할 수 있음
가비지 컬렉터의 메모리 회수
가비지 컬렉터는 지정된 시간에 따라 주기적으로 메모리를 회수
Garbage 플래그로 설정된 오브젝트를 파악하고 메모리를 안전하게 회수
Garbage 플래그는 수동으로 설정하는 것이 아닌, 시스템이 알아서 설정함
한 번 생성된 언리얼 오브젝트는 바로 삭제가 불가능함 (레퍼런스 정보를 없애고 언리얼 GC가 회수하도록 설정)
RootSet 플래그의 설정
AddToRoot 함수를 호출해 루트셋 플래그를 설정하면 최초 탐색 목록으로 설정됨
루트셋으로 설정된 언리얼 오브젝트는 메모리 회수로부터 보호받음
RemoveFromRoot 함수를 호출해 루트셋 플래그를 제거할 수 있음

콘텐츠 관련 오브젝트에 루트셋을 설정하는 방법은 권장되진 않음
오브젝트 선언의 기본 원칙
오브젝트 포인터는 가급적 UPROPERTY로 선언하고,
메모리는 가비지 컬렉터가 자동으로 관리하도록 위임한다.
class UNREALMEMORY_API FStudentManager : public FGCObject
{
...
virtual void AddReferencedObjects(FReferenceCollector& Collector) override;
virtual FString GetReferencerName() const override
{
return TEXT("FStudentManager");
}
private:
class UStudent* SafeStudent = nullptr;
};
// MyGameInstance.h
UCLASS()
class UNREALMEMORY_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
virtual void Init() override; // 어플리케이션이 초기화될 때 호출
virtual void Shutdown() override; // 어플리케이션이 종료될 때 호출
private:
TObjectPtr<class UStudent> NonPropStudent;
UPROPERTY()
TObjectPtr<class UStudent> PropStudent;
TArray<TObjectPtr<class UStudent>> NonPropStudents;
UPROPERTY()
TArray<TObjectPtr<class UStudent>> PropStudents;
};
// MyGameInstance.cpp
void CheckUObjectIsValid(const UObject* InObject, const FString& InTag)
{
// ::IsValid() 대신 보다 정교하게 체크해줄 수 있는 함수 사용
if (InObject->IsValidLowLevel())
UE_LOG(LogTemp, Log, Text("[%s] 유효한 언리얼 오브젝트"), *InTag);
else
UE_LOG(LogTemp, Log, Text("[%s] 유효하지 않은 언리얼 오브젝트"), *InTag);
}
void CheckUObjectIsNull(const UObject* InObject, const FString& InTag)
{
if (InObject == nullptr)
UE_LOG(LogTemp, Log, Text("[%s] nullptr 언리얼 오브젝트"), *InTag);
else
UE_LOG(LogTemp, Log, Text("[%s] nullptr 아닌 언리얼 오브젝트"), *InTag);
}
void UMyGameInstance::Init()
{
Super::Init();
NonPropStudent = NewObject<UStudent>();
PropStudent = NewObject<UStudent>();
NonPropStudents.Add(NewObject<UStudent>());
PropStudents.Add(NewObject<UStudent>());
}
void UMyGameInstance::Shutdown()
{
Super::Shutdown();
CheckUObjectIsNull(NonPropStudent, TEXT("NonPropStudent")); // nullptr 아님 (댕글링 포인터)
CheckUObjectIsValid(NonPropStudent, TEXT("NonPropStudent")); // 유효하지 않음
CheckUObjectIsNull(PropStudent, TEXT("PropStudent")); // nullptr 아님
CheckUObjectIsValid(PropStudent, TEXT("PropStudent")); // 유효함
CheckUObjectIsNull(NonPropStudents[0], TEXT("NonPropStudents")); // nullptr 아님 (댕글링 포인터)
CheckUObjectIsValid(NonPropStudents[0], TEXT("NonPropStudents")); // 유효하지 않음
CheckUObjectIsNull(PropStudents[0], TEXT("PropStudents")); // nullptr 아님
CheckUObjectIsValid(PropStudents[0], TEXT("PropStudents")); // 유효함
}
// StudentManager.h
class UNREALMEMORY_API FStudentManager
{
public:
FStudentManager(class UStudent* InStudent) : SafeStudent(InStudent) {}
const class UStudent* GetStudent() const { return SafeStudent; }
private:
class UStudent* SafeStudent = nullptr;
};
// MyGameInstance.h
UCLASS()
class UNREALMEMORY_API UMyGameInstance : public UGameInstance
{
...
class FStudentManager* StudentManager = nullptr;
};
// MyGameInstance.cpp
void UMyGameInstance::Init()
{
Super::Init();
StudentManager = new FStudentManager(NewObject<UStudent>());
}
void UMyGameInstance::Shutdown()
{
Super::Shutdown();
const UStudent* StudentInManager = StudentManager->GetStudent();
delete StudentManager;
StudentManager = nullptr;
CheckUObjectIsNull(StudentInManager, TEXT("StudentInManager")); // nullptr 아님 (댕글링 포인터)
CheckUObjectIsValid(StudentInManager, TEXT("StudentInManager")); // 유효하지 않음
}
// StudentManager.h
class UNREALMEMORY_API FStudentManager : public FGCObject
{
...
virtual void AddReferencedObjects(FReferenceCollector& Collector) override
{
if (SafeStudent->IsValidLowLevel())
Collector.AddReferencedObject(SafeStudent);
}
virtual FString GetReferencerName() const override
{
return TEXT("FStudentManager");
}
...
};
// MyGameInstance.cpp
void UMyGameInstance::Shutdown()
{
...
CheckUObjectIsNull(StudentInManager, TEXT("StudentInManager")); // nullptr 아님
CheckUObjectIsValid(StudentInManager, TEXT("StudentInManager")); // 유효함
}