Ch03 Memory
GC
원리
Reference Graph 를 주기적으로 탐색해 메모리를 지움.
Reference 에 잡는 법은 아래의 3가지 방법으로 1번째 방법으로 왠만한 경우가 해결 됨.
UPROPERTY
로 잡은__,__ 포인터, static array(int a[10]
같은거) 또는 UE4 가 제공하는 컨테이너(TARRAY
같은거 )UObject::AddReferencedObjects
의 오버라이드로 추가- Actor-Component 가 이걸로 기본으로 등록됨
UObject::AddToRoot
인 메소드 호출- Root 에 있는건 삭제되지 않는데 어쩔 수 없는 경우에만 사용
레퍼런스가 안잡히는 UObject
이하의 애들은 다음 GC Cycle 에 삭제 됨.
UStruct
는 UObject
의 자식이 아니기 때문에 GC 처리되지 않으므로 필요하면 위의 3가지마 방법으로 레퍼런스를 잡아줘야함.
GC Cycle 은 Game Thread 에서 실행되므로 Object 내부의 함수 도중에 GC 는 시행안됨 .
- 중간에
GetWorld()->ForceGarbageCollection(true);
로 실행시는 보장안됨.
사용
NewObject
로 생성한 애들이 적용되지, SpawnActor
는 적용 안됨 .
UPROPERTY
애들은 삭제될 때 nullptr
로 초기화 됨.
bool IsValid(const UObject* test)
함수가 삭제 체크검사 + null 체크로 유용함
GetWorld()->ForceGarbageCollection(true);
로 어쩔 수 없을 때 강제 로 GC 가능.
- 단 이때 함수 도중에 GC 가 발동되므로
IsValid
로도 삭제예정인지 할 수 없음. 얘는 삭제할 예정인지만 검사할 수 있기 때문임. 그러므로GameMode
의 Load 등에만 사용권장.
직접 만든 객체를 UE4 가 관리하는 GC System 에 넣으려면 FGCObject
를 상속해야함.
GC 가 삭제한 메모리 참조시 Read Access Violation - 0XFFFFF
어쩌로 그럼.
기타
Project Setting -> Engine -> Garbage Collection 에 옵션이 있음.
생성
Create
- Instance
- 예제코드
auto actor = NewObject<UObject>(this, strref_class.TryLoadClass<AActor>(), "Name"); actor->ConditionalBeginDestroy(); // 수동메모리해제요청(다음 GC 에 해제)
- 참고
- outer 에 대해서
- ConstructObject is deprecated . UClass 로 생성하는 경우 NewObject 의 두번째 인자에 넣어주면 오버로딩이 됨.(참고)
- 소멸 및 GC 요청은
ConditionalBeginDestroy()
메소드 호출
- 예제코드
- World Spawn
- 월드 배치는
AActor
부터 월드에 대한 Transform 을 객체가 갖기 때문에 접두사가A
가 붙은 클래스만 가능함. GetWorld()->SpawnActor<AActor>(strref_class.TryLoadClass<AActor>())
이런식- 에디터 상에서 표시되는 Subclass 의 경우
CreateDefaultSubobject
를 생성자 에서 씀. - 소멸 및 GC 요청은
Destroy()
메소드 호출.
- 월드 배치는
Smart Ptr
사용자 정의 자료형용
- 설명
- 참고
- 플랫폼 간의 호환성으로 사용하지 않는 STL 의 smart pointer 와 거의 비슷한 내용임
- UE4 차원에서 생성 관리하므로 UObject 에서 쓰면 안됨.(주로 소멸시 터짐)
- 아직 배열단위로 관리가 안됨(소멸자가 안됨)
- TUniquePtr
- 스레드에서 안전하지 않음.
- 복사 생성자 만날 시 소유권이 이전되어 전달하던 포인터는 유효하지 않게 됨.
- TSharedPtr
- Template 2번째 인자로 스레드 안전한한 포인터도 쓸 수 있음.
TSharedRef
으로 변환가능한데 차이는Get()
사용시 reference 형태로 리턴된다는 것.- 형변환은 Upcasting 의 경우 묵시적 변환이 되고, Downcasting 의 경우
StaticCastSharedPtr<BBB>(shared_aaa);
나StaticCastSharedRef<BBB>(shared_aaa);
로 가능.
- TWeekPtr
shared_ptr
에서 묵시적으로 변환가능.TSharedPtr
의 참조카운터를 올리지 않고 그 SharedPtr 가 유효한지 아닌지 파악가능- 상대적으로 느림
UObject 이하 자료형용
- TWeakObjectPtr
- GC Refence Graph 에 잡히지 않는 UObject 이하의 애들은 다음 GC 에 사라질 위협에 있음.
- 그렇다고 모든 UObject 이하의 애들을
UPROPERTY
로 놔둘수는 없음 - 그렇다고 그냥 포인터로는 GC 에서 사라졌는지 체크가 안됨.
TWeakObjectPtr
은 가능함.MakeWeakObjectPtr<T>(T*)
로 생성가능
- TSoftObjectPtr
- 참고할 UE4 공식 문서
- 원하는 객체에 대한 String 을 가지는
FSoftObjectPath
을 래핑하는 포인터 - 비동기 로딩을 하는 객체를 지정하는 포인터가 될 수 있음
return Loaded ? obj else nullptr;
- 단순히 널체크로도 확인할 수 있고
IsPending()
으로 지금 로드중인지 확인가능 - 로드 중인지 체크만 해주는거고 로드는 코드 등으로 직접 해줘야햠.
- 특히 유용한 경우는
UPROPERTY
로 만든TSoftObjectPtr
을 Level 의 정적 객체와 연결할 수 있다는 것임.
댓글남기기