Memory management implications

I understand that the course is introducing things step by step, but this was the first time in the course when I was really uncomfortable following along, because my engineering background was raising all kinds of red flags.

How close is this implementation to a real life scenario? More specifically, how exactly the engine will manage memory in this case?

The way I see this, the thank has a pointer to the health component, which has a pointer to the game mode, which has a pointer to the tank. This creates a “reference loop” which in languages that I’m more familiar with than C++ (like Swift, for example) is a big NO-NO, because it will create a memory leak. The same with the tank having a pointer to the player controller which internally has a pointer to the controlled pawn (which is the tank).

Are reference loops a problem in UE, or the garbage collector can still figure out what is not used anymore and free the memory?

Intuitively I was using TWeakObjectPtr<> everywhere I could, but I don’t know if this is the right approach here.

UObjects are generally managed by the garbage collector. From the docs:

Object destruction is handled automatically by the garbage collection system when an Object is no longer referenced. This means that no UPROPERTY pointers, or engine containers or smart pointer class instances should have any strong references to it. When the garbage collector runs, unreferenced Objects that are found will be deleted. In addition, the function MarkPendingKill() can be called directly on an Object, and this function will set all pointers to the Object to NULL, as well as remove the Object from global searches. Once again, the Object will be fully deleted on the next garbage collection pass.

That would mean you might experience the opposite of a memory leak, where the garbage collector will free it from memory even when you still have a valid pointer pointing to it. As that’s basically its purpose, when don’t want to prevent the garbage collector freeing the memory.

Note that Weak Pointers have no impact on whether an Object is garbage collected or not.

FWeakObjectPtr is a weak pointer to a UObject. It can return nullptr later if the object is garbage collected. It has no impact on if the object is garbage collected or not. It can’t be directly used across a network.

(TWeakObjectPtr is a template wrapping a FWeakObjectPtr)

Ok, so from the same documentation:

A reference cycle exists whenever two or more objects use Smart Pointers to keep strong references to each other. In these situations, the objects protect each other from deletion, as each one is always being referenced by one other object, and so neither can be deleted while the other still exists. If no outside object references either of the objects in the reference cycle, they will effectively leak. Weak Pointers can break these reference cycles, because Weak Pointers do not preserve the objects they reference. Use Weak Pointers when you want to reference objects without claiming ownership over them and potentially extending their lifespans.

And then from a section on object management:

When an AActor or UActorComponent is destroyed or otherwise removed from play, all references to it that are visible to the reflection system ( UProperty pointers and pointers stored in UProperty Unreal Engine container classes such as TArray ) are automatically nulled. This is beneficial in that it prevents dangling pointers from persisting and causing trouble down the road, but it also means that AActor and UActorComponent pointers can become null if some other piece of code destroys them. The ultimate advantage of this is that null-checking is more reliable, as it detects both standard-case null pointers and cases where a non-null pointer would have been pointing at deleted memory.

It is important to realize that this feature applies only to UActorComponent or AActor pointers marked with UPROPERTY , or Unreal Engine container class that store UActorComponent or AActor pointers and are marked with UPROPERTY . A raw UObject stored in a raw pointer will be unknown to the Unreal Engine, and will not be automatically nulled, nor will it prevent garbage collection. Note this does not mean that all UObject* variables must be UProperties . If you want an Object pointer that is not a UProperty , consider using TWeakObjectPtr . This is a “weak” pointer, meaning it will not prevent garbage collection, but it can be queried for validity before being accessed and will be set to null if the Object it points to is destroyed.

From this I conclude that all UObject pointers should either be marked as UPROPERTY or wrapped into a Smart Pointer with appropriate semantics, otherwise you can end up with memory leaks or stale pointers. Is this accurate?

Mostly. Actors spawned into the world would be kept alive by the world it was spawned in and freed when the world is destroyed. Similarly components would be kept alive by the actor it’s attached to.

As for other things, definitely. It’s happened a couple times now that a student didn’t mark their widgets as UPROPERTY() and then had the garbage collector come and free it from memory as they were still using it which obviously caused problems when their code would dereference that pointer that now pointed to invalid memory.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms