non-UPROPERTY UObject garbage collection

Hi, I am new to UE and C++, By what I understood from c++ [intro page][1] , UObjects which are not marked with UPROPERTY will get GCed. here is the ScreenShot of the page.

I wrote one experiment code to understand this which looks like this:

UPROPERTY() 
UObject *obj1;

UObject *obj2;

float time;

// Sets default values for this component's properties
UWaveActor::UWaveActor()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;
	obj1 = NewObject<UObject>();
	obj2 = NewObject<UObject>();
	// ...
}

// Called every frame
void UWaveActor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	if (obj2 != nullptr)
	{
		Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	AActor *ad = GetOwner();
	FVector pos = ad->GetActorLocation();
	time += DeltaTime;
	pos.Z = FMath::Sin(time)*5.0f;
	ad->SetActorLocation(pos);
	}
}

and called GEngine->ForceGarbageCollection(true) from another actor component, which should destroy obj2 but the actor is still animating so obj2 is not destroyed. I misunderstood something or missing something, any help will be appreciated.

Your obj2 is not set nullptr when the object is garbage collected, because it (your raw pointer to the object) is not known to GC. Your pointer will simply keep pointing to where that object was located in memory. This memory location may or may not be still insde the process adress space, and may either cause the program to behave undefined, or may crash as soon as you try to dereference that obj2 pointer.

You can use TWeakObjectPointer<UObject> instead of UObject* for your test. TWeakObjectPointer will not prevent the object from being garbage collected, but GC knows about the existence and will set it to invalid. TWeakObjectPointer has an IsValid() function for checking validity of the pointer.

1 Like

You are correct, i forgot about invalid pointers dummy me ^^’ Pointer works like integer containing memory address, nullptr is 0 if it’s not nulled by reflection system (UPROPERTY()) it will be left with old address which will cause obj2 != nullptr to always return true as it is not 0 and pass the if. Since your code in if don’t reference to obj2 it does not crash either.

Other way to check validity of pointer is calling IsValidLowLevel() on it. But it is quite expensive operation and should be avoided if possible.