How UE4 ensure TWeakObjectPtr::Get()'s return UObject* pointer safe?

Hi,
I am a newer,
I have a question about Smart Pointer usage in UObject objects, blow is the description:

Usually, I have a member UObject* field tagged by UPROPERTY() in a AActor class ( we call it HOLDER for for), and have a TWeakObjectPtr smart pointer (refers to HOLDER) hold by another class (we call it USER for now).
the USER :
if (auto *ptr = weakObjectptr.Get())
{
//some long time run process use ptr .

}
When the HOLDER drop the UObject instance, the instance will be deleted by GC in the future.
As I know, if USER run in a different thread, the USER will use a unvalid ptr for a while, some crash will occors, but it NOT!!

I think there is some magic in the TWeakObjectPtr::Get function. Any one know how ue4 engine protects the returned ptr?

It doesn’t - TWeakObjectPtr is actually just two integers. Everytime you dereference it, it searches the global GC map to “find” the object and returns it so long as it isn’t “pending kill” (AKA “marked for garbage” in UE5). This is also why they are considerably slower to dereference than a regular pointer. The difference is slight, but not negligible,

TWeakObjectPtr exists for one reason only - to safely keep a reference to a UObject outside of the reflection system, such as within slate, or a struct that you are creating as part of a TSharedPtr etc etc. They are not meant to replace UPROPERTY() nor convey object ownership. It’s absolutely unsafe to read from a UObject on another thread if you think that object has been destroyed/GC’d - it will NOT be kept alive by TWeakObjectPtr. This is why the virtual ReadyForFinishDestroy() function exists - returning false here means GC will not fully destroy the object until you have cleaned up your other threads (i.e, you are managing the GC time yourself)

A common misconception is that UPROPERTY() will prevent an object from being GC’d, but this is NOT true - an object which has been explicitly marked as garbage WILL be GC’d, and all UPROPERTY() references to that object will be automatically set to null when it is. To check whether an object is still valid, you use the IsValid(Object) global function before using it. If you want the object to be destroyed, you call MarkAsGarbage() on it.

Destroying actors and/or components will automatically mark themselves as garbage when destroyed. Other objects (including UMG widgets) do not.

1 Like

Thanks a lot!