TMap and garbarge collection

Hello,

So I’d like to have a TMap where key is an AActor* and value is some struct with data.

As it was mentioned in the docs, TMap can’t be a UPROPETY and is therefor not a safe container for UObject* pointers. Basically an AActor* pointer can become invalid or, which seems to be much worse, it’s memory could be overridden by GC with some other AActor object without me even noticing that. Is this correct?

What is the “right” way of handling this? Do I wrap my AActor* pointer into a WeakObjPtr and check FWeakObjPtr.IsValid() then? Or is there a better solution?

Best regards

Hi ,

Unfortunately, I think it’s not good idea to use TMap with AActor* key.
But, if you really need to do this, you can try to use TWeakObjectPtr and do something like this:

for (TMap<TWeakObjectPtr<AActor>, INT32>::TIterator MapIt(TestTMap); MapIt; ++MapIt)
 {
  if (!MapIt.Key().IsValid())
   TestTMap.Remove(MapIt.Key());  
 }

But it’s really not good idea!

If you give me more information, I can supporting you better solution.

Best,

Thx for the anser, . Why exactly is it not a good idea? Could you please explain?

Here is some background: I’m saving some information about the actor in the map like: TMap, AActor* as key, FMyStateStruct as value Think about some kind of combat state. Every so many ticks I iterate over the map, remove invalid actors (!there is the problem!) and update the state as game logic needs it.

At some point other game systems may ask about the actors combat state so they call method like: FMyStateStruct MyClass::GetActorState(AActor*), hence the TMap and not TArray.

Hey ,
It’s not good, because periodically need to check for validity of Actor*, in other way, it can provide memory leak.

In your case any ActorClass can have combat state or only yours reimplemented actors?

But checking for validity is necessary in any case isn’t it? I mean If I have to iterate over some specific group of actors in my world periodically and I hold them, let’s say in a TArray then I still need to ask: if (IsValid(Actor)) to check for pending kill or NULL before I can start manipulate it, right?

for(auto It = MyArray.CreateIterator(); It; ++It)
{
   If (IsValid(*It))
   {
       // Do smth. with actor
    }
}

Yes, it right.
The best way for this is make your own actor class for example MyActorWithComboState extends AActor and in Destroyed() event remove it from MyArray or MyTMap. This is way without checking for validity.