I’ll do something like this:
if(IsValid(somePointer)) { ... }
Most of the time this returns what you’d expect: true if the pointer is valid, false if the pointer is null or points to a destroyed/invalid object. But sometimes, it will instead throw this:
Assertion failed: Index >= 0 [File:c:\repositories\ue-deploy\unrealengine\engine\source\runtime\coreuobject\public\UObject/UObjectArray.h] [Line: 455]
The same exact code will work correctly on one run of the game and then throw the assert on the next, or vice-versa. Just… roll the dice.
In the particular case I’m looking at right now, the pointer in question is set to nullptr in the header declaration, so it’s not like it’s uninitialized garbage or anything. I have extremely straightforward, very basic logic for spawning an actor to this pointer some time after starting a game session, and then the actor is destroyed some time after that. I’ve seen this assert happen when checking the pointer before the actor’s creation, during the actor’s lifetime, and after the actor is destroyed… always inconsistently.
I don’t even really understand what this assert is. As best as I can tell from looking at the code, it seems like someone’s passing in an invalid Index (<0) to FUObjectArray::IndexToObject(). We get there by way of IsValid() calling UObjectBaseUtility::IsPendingKill(), which does this:
return GUObjectArray.IndexToObject(InternalIndex)->IsPendingKill();
And the InternalIndex value is apparently just… bad. So we never even get to find out if our object is pending kill.
My best guess would be that the object has been fully destroyed by this point, but if that’s the case, then doesn’t it render IsValid() kind of useless?
Is there something I’m missing, here?