Memory Management

There are a few different memory management systems in UE4: garbage collection, smart pointers, and standard C++ memory management. Garbage Collection Garbage collection (GC) tracks UObject sub-cla...

Updated almost 4 years ago

There are a few different memory management systems in UE4: garbage collection, smart pointers, and standard C++ memory management.

Garbage Collection

Garbage collection (GC) tracks

UObject

sub-classes, which include

[https://docs.unrealengine.com/en-US/API/Runtime/Engine/GameFramework/AActor/index.html AActor]

and

[https://docs.unrealengine.com/en-US/API/Runtime/Engine/Components/UActorComponent/index.html UActorComponent]

.

Objects are primarily kept alive in 3 ways:

  • By having a strong reference (
    [https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties/index.html UPROPERTY]
    
    ) to them (from objects that are also referenced)
  • By adding them to the list of
    void UObject::AddReferencedObjects(UObject* This, FReferenceCollector& Collector)
    
    (from objects that are also referenced)
  • By adding them to the root set with
    [https://docs.unrealengine.com/en-US/API/Runtime/CoreUObject/UObject/UObjectBaseUtility/AddToRoot/index.html UObject::AddToRoot]
    
    (typically unnecessary)

When objects do not fulfill any of the above conditions, on the next GC cycle they will be marked as unreachable and garbage collected (destroyed).
To force the destruction of objects that are still reachable, you can call

MarkPendingKill

on them, and it will force their destruction on the next GC cycle (you generally want to avoid doing this as that is what the garbage collection is for, and some classes, like

AActor

and

UActorComponent

do not support it).
The destruction of an object doesn't necessarily all happen in the same frame, when garbage collection starts on it, it will first call

BeginDestroy

(do not call this yourself), then, when ready

FinishDestroy

.
The GC runs in the game thread so it won't ever run as your are accessing an object from the game thread.

While the most common way of keeping alive objects is through a

[https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties/index.html UPROPERTY]

, actors and components work differently:
levels reference their actors and actors reference their components. Both work by overriding the

void UObject::AddReferencedObjects(UObject* This, FReferenceCollector& Collector)

implementation and collecting what they do not want to be garbage collected. This means that even if there are no strong references to actors and components with an owner, they won't be garbage collected until manually destroyed, or their level is unloaded.

The garbage collector will clear references to garbage collected objects in any of these cases[1]:

  • A raw pointer declared with
    [https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties/index.html UPROPERTY]
    
  • In a
    UObject
    
    compatible container, such as
    TArray
    
    ,
    TSet
    
    , or
    TMap
    
    , if declared with
    [https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties/index.html UPROPERTY]
    
  • In a
    TWeakObjectPtr
    
    (the reference isn't exactly cleared in this case but calling
    Get
    
    will now return nullptr)

Anytime code references an

AActor

or a

UActorComponent

, it has to deal with the possibility that

AActor::Destroy

is called on the actor or

UActorComponent::DestroyComponent

is called on the component. These functions will mark them for pending kill, thus triggering their garbage collection at the first chance it gets (note that destroying an actor also destroys all its component). Since the garbage collector automatically nulls out

[https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Properties/index.html UPROPERTY]

pointers when it actually gets to destroy them, null-checking an actor or component pointer is sufficient to know it's safe to use, though you might also want to check

IsPendingKill

on them to avoid accessing them after they have been marked for destruction (

TWeakObjectPtr

already checks for this when retrieving the raw pointer).

If you write your own non-garbage classes that references garbage collected objects, you may want to sub-class

[https://docs.unrealengine.com/en-US/API/Runtime/CoreUObject/UObject/FGCObject/index.html FCObject]

.

Unreal Smart Pointer Library

The Unreal Smart Pointer Library is for code that is not based on the UObject system. It is similar in function to the C++11 standard library smart pointers. Unreal Smart Pointers cannot be used to reference UObjects, because the garbage collector isn't aware of smart pointers[2].

Further reading

Documentation

Other

References

  1. Unreal Object Handling | Automatic Updating of References
  2. Unreal Smart Pointer Library