My goal is to remove a component (UBoxComponent) from a scene and out of memory. The above code seems to crash the program, especially after line 845 executes, on the 17th iteration. The error seems to be “illegal name block index out of range” according to the debugger. Commenting out DestroyComponent() and leaving UnregisterComponent() seems to solve the problem. But I’m confused why this is happening? Shouldn’t DestroyComponent accomplish what I want to do? Does UnregisterComponent() remove the object (UBoxComponent) from memory as well?
Hi @Moon515
Check all your pointer before use it.
if(IsValid(MyPointer))
{
//use MyPointer here
}
It seems that your counter (i) exceeds the size of the array.
Try deleting the array element outside the for loop
Maybe when you delete the element the size of the array changes and that is causing the problem
in addition… (2ms) seems like too much CPU time.
If you’re going to (continuously create and destroy those boxes)… you better not destroy them.
Recycle them…
Or you will have a significant FPS drop.
The weird part is there doesn’t seem to be an out of bounds issue when looking at the debugger. Like I wrote in the original post, the crash occurs during the 17th iteration after DestroyComponent is called. As you can see, 17 is a valid index in the TArray and UBoxComponent seems to point to a valid object.
Did you put UPROPERTY() on your BoxComponents?
The garbage collector may have removed the pointers.
UPROPERTY() Prevent the garbage collector from killing your pointers
@Ivan3z
Yes, I did inside the UStruct declaration of the object.
Are you instantiating the object?
Anyway… when you do this:
arr[i].box_component = nullptr;
The garbage collector detects that the pointer does not point anywhere and will free the memory automatically.
Then I think there is not need to destroy the object. The GC will do it for you.
So are you saying setting arr[i].box_component = nullptr; works as a workaround? An alternative from using DestroyComponent()? Just use UnregisterComponent and set the UBoxComponent to null?
Here is the instantiation code:
for(int i = 0; i < 4; i++){
FObject object;
object.box_component = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass());
object.box_component->RegisterComponent();
object.box_component->SetWorldLocation(FVector(shape.origin.X, shape.origin.Y, shape.origin.Z));
object.box_component->SetBoxExtent(shape.size);
object.box_component->bHiddenInGame = false;
object.box_component->SetGenerateOverlapEvents(true);
int32 index = arr.Add(object);
}
I have honestly never destroyed a component… so far I haven’t needed to.
But theoretically it should work.
Note that the garbage collector does not destroy the object immediately.
It does it from time to time.
But I think it’s every few seconds… I think that’s set in the DefaultEngine.ini file
suggestions (that won’t fix your issue):
- i think you should do “i>= 0”
- use RemoveAtSwap
- check for IsValid(Arr[i].box_component) in the loop before trying to destroy. isValid checks for pending delete. you might be trying to destroy the same component multiple times.
also i highly doubt you need to unregister before calling destroy. but i might be wrong. it does seems like a good idea. but it might also create issues not sure.
i do not remember if components should be manually destroyed.
afaik objects created with NewObject can’t really be manually destroyed in a simple manner. you’d have to wait for the GC to do it. so the suggestion of just setting to nullptr and wait it’s a good one.
in that case calling unregister seems like a good idea. but i’m unsure.
I just realized this
Declare you array like this:
UPROPERTY()
TArray<UBoxComponent*> Arr;
You need to protect the array from the garbage collector.
@Ivan3z ,
I already have it labeled with Uproperty
UPROPERTY(VisibleAnywhere)
TArray<FObject> arr;
where FObject:
USTRUCT()
struct FObject{
GENERATED_BODY()
....
UPROPERTY()
UBoxComponent * box_component;
};
Tried commenting out UnregisterComponent(), and left DestroyComponent() alone but the program still crashes after DestroyComponent() executes at the 17th index.
Added the isValid function but the problem still occurs. As you can see from the debugger, the object exists at the problematic index:
Use this
arr[i].box_component = nullptr;
instead of this
DestroyComponent()
left GC do its work…
sidenote:
yes, i’ve read that on your previous post.
as i’ve said before isvalid also checks for an object pending destruction. which would avoid double destruction.
i’d go with Ivan3z suggestion.