Game crashes after checking a pointer after a certain amount of time

Hello answerhub!

I’ve been working on a game to much success, thanks in large part to many of the answers posted here, but my game has begun to crash under a very specific set of circumstances, and I was wondering if answerhub could shed some light on it.

Effectively, the game is a brawler, and to handle player attacks I spawn and destroy BoxComponents to function as hitboxes. It is working quite well, but I wanted to make the character snap out of their current animation if they walked off a platform. To do this, I simply made a function that resets the character to the default state (no hitboxes or special properties) and caused it to run when Movementmode changed away from walking.

However, this seems to have introduced a very odd crash: whenever my character spawns a hitbox, then destroys that hitbox (due to the move being over), then waits 30 or so seconds and walks off a ledge, the game crashes.

Interestingly enough, if a character spawns a hitbox, destroys that hitbox, and then walks off a ledge before a long period of time has passed, no crash occurs.

My only thought is that something happens in the process of destroying an object that I do not yet understand.

A crash log is available here: http://pastebin.com/j1hPVP3x

The main interesting part of this crash log is that it mentions ‘ResetState() on line 190.’ Line 190 is the line that calls DestroyHitbox(), seen in my code below.

Here is the relevant code:

.h

public:
	// Called to cancel an animation preemptively.
	// Resets animation variables.
	void ResetState();

	// Called when movement mode changes. Useful for pulling us out of certain states.
	// (i.e. stopping slash if you slash off the side)
	virtual void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode) override;

	// This blueprint-callable function spawns or repositions a hitbox. Eventually we'll look into supporting more than one if needed.
	UFUNCTION(BlueprintCallable, Category = "ScuffleFunctions")
		void SpawnHitbox(FVector Offset, FVector Size);

	// This blueprint-callable function destroys the hitbox.
	UFUNCTION(BlueprintCallable, Category = "ScuffleFunctions")
		void DestroyHitbox();

private:

	/** COMPONENTS **/

	// The hitbox component. Currently there can only be one.
	UBoxComponent* BoxComponent;

.cpp

void AScuffleCharacter::ResetState()
{
	// End any anim montage playing
	StopAnimMontage();
	
	// Reset everything to its default values, similar to firing EndSliding, etc.
	bCanMove = true;
	bIsInvincible = false;
	bIsParrying = false;

	UCharacterMovementComponent* MoveComp = GetCharacterMovement();
	if (MoveComp)
	{
		UScuffleCharacterMovement* MyMoveComp = Cast<UScuffleCharacterMovement>(MoveComp);
		if (MyMoveComp)
		{
			MyMoveComp->bIsSliding = false;
		}
	}

	// Also clean up any state-dependant hitboxes.
	DestroyHitbox();
}

void AScuffleCharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode)
{
	if (PrevMovementMode == EMovementMode::MOVE_Walking)
	{
		ResetState();
	}
}

void AScuffleCharacter::SpawnHitbox(FVector Offset, FVector Size)
{
	DestroyHitbox();
	BoxComponent = NewObject<UBoxComponent>(this, UBoxComponent::StaticClass());
	if (BoxComponent)
	{
		BoxComponent->RegisterComponent();
		BoxComponent->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale, NAME_None);
		if (bIsFacingRight)
		{
			BoxComponent->SetRelativeLocation(Offset);
		}
		else
		{
			BoxComponent->SetRelativeLocation(-Offset);
		}
		BoxComponent->SetBoxExtent(Size);
		BoxComponent->SetHiddenInGame(bShouldHideHitboxes);
		BoxComponent->SetCollisionProfileName(FName("Hitbox"));
		BoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AScuffleCharacter::OnHitboxOverlap);
		BoxComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
		BoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly); // Don't know why, but toggling this updates overlaps
		BoxComponent->UpdateOverlaps();
	}
}

void AScuffleCharacter::DestroyHitbox()
{
	if (BoxComponent)
	{
		BoxComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
		BoxComponent->DestroyComponent();
	}
}

Can anyone tell me why this crash occurs, or why it occurs specifically when waiting a large amount of time between a hitbox being destroyed and running DestroyHitbox()? I would not expect this to happen, given that I check to see if BoxComponent is valid before using it as a pointer.

Thanks for any help! You all are great! Please let me know if I can provide more information. I’m even happy to link the entire project if that would help.

So I think I fixed it! Turns out, it’s very important to set component pointers you have destroyed to NULL! I had assumed checking with an IF statement would have caught it, but turns out it doesn’t. That fixed my problem, anyway. So if you find this question in the future, be sure you are setting any pointer to a component you have destroyed to NULL!