Help! There's something wrong with my TArray/Struct

Hello!

All I’m doing is storing the mouse position at intervals. I store these as FVector2D in a TArray.

Very simple ,works great. But after 60 seconds it crashes with…

Access violation reading location

And breaks on line 1468 of TArray.h

CopyConstructItems(GetTypedData(), Source.GetTypedData(), SourceCount);

The script in which this lies inherits from UObject and is attached to the player controller. This array is in a struct. I tried saving them to an array declared in the class. But then copying to the struct then fails.

I suspect it’s to do with GC but I don’t know how to prevent it? New to C++ as it is!

Any and all help is appreciated!

Edit: I should also add, I’m not storing huge numbers of items in the array. It’s only when I click and drag I sample positions. And clear the list each time. The error occurs when I Empty/Initialize on a new drag, after 60 seconds.

Edit: Came across this but there’s no solution and I can’t access the link provided.

It sounds that you running out of array index space (but im not sure), maybe you should higher the intervals, remove old data in array (for GC your data in active object in array is too important to be removed) or try different container types:

Can you attach or pastebin the relevant code?

Please also post the callstack of the crash, thanks!

I store at most 30-50 items in the array. It’s only when I empty it that the problem occurs (after 60 seconds). All is fine until then, even if I purposefully store a huge number of items.

It crashes after 60 seconds when I…

Points.Reset();
//or
Points.Empty();
//or
Points.Add(thePoint);

Even if I do nothing with the array prior to 60 seconds.

So I just caused the error again to copy the call stack. This time it broke on line 868 of Array.h.

Here’s the callstack:
http://pastebin.com/raw.php?i=akmP1uRP

And here’s the callstack if I use an array declared in the class, instead of a ustruct…:
http://pastebin.com/raw.php?i=aXJuKgHg

Looking at the callstack, my best bet is that the object that holds your TArray does no longer exist. How are you getting access to this object? Is it possible that you are saving a pointer to this object somewhere? Did you make any modifications in UElementalGestureListener::AddPointToShape by any chance? Can you show me more of the code that you modified and/or added?

Here’s the call stack when it crashes at the location mentioned in the original post (ln. 1468 > Array.h)
http://pastebin.com/raw.php?i=G2gJc7x0

I assume it’s all the same problem. It just happens to break in a different place if I’m adding to the list, resetting the current list or re-initializing the struct that owns it, once I pass the 60 seconds.

Also, thanks for helping by the way!

I add the component to the player controller like this

   .h
    public:
    TSubobjectPtr<class UElementalGestureListener> GListener;


.cpp (initializer)
GListener = PCIP.CreateDefaultSubobject<UElementalGestureListener>(this, TEXT("GestureListener"));

/*Then I call my drag start/update/end methods from the player controller. Was using delegates, but come to think of it, they were causing issues after a while! They were losing their reference. Possibly the same problem? So I changed and directly called the methods.*/

void AElementalPlayerController::OnSwipeStarted(const FVector2D& AnchorPosition, float DownTime)
...
GListener->OnDragStart(AnchorPosition); 
//OnDragStartDelegate.ExecuteIfBound(AnchorPosition); //Breaks after a duration

Here’s a stripped down version of UElementalGestureListener

The CurrentGesture struct is declared like this

(Public)
UPROPERTY(EditAnywhere, Category = Data)
	FGesture CurrentGesture;

And the relevant structs…

    USTRUCT()
    struct FGesture
    {
    	GENERATED_USTRUCT_BODY()
    
    	UPROPERTY(EditDefaultsOnly, Category = Data)
    	FShape Shape;
    }
    USTRUCT()
    struct FShape
    {
    	GENERATED_USTRUCT_BODY()
    
    	UPROPERTY(EditDefaultsOnly, Category = Data)
    		TArray<struct FVector2D> Points;
    
        //Adding this made no difference
        FShape()
    	{		
    		Points.Reset();
    	}
    }

Sorry, I guess I would have to see more code for any of this to make sense.

I think what’s happening is that, by the time the event delegate for the swipe event is called, the object that holds your array is already destroyed. Your object was likely removed by the garbage collector that runs every once in a while. UObject instances will be destroyed if no other UObjects hold a reference to them, i.e. the instance is orphaned. The garbage collector will detect this and destroy the object.

How does the PlayerController reference the GestureListener?

That’s all there is to it really.

FGesture contains FShape which contains TArray. Then the above linked class does the rest.

The GestureListener is a UObject but the player controller seems to reference it fine. Very confusing.

I’ll re-implement the delegates and see what the error was, and if it was after 60 seconds. Might shed some more light on it…

public:
TSubobjectPtr GListener;

How would I then add the component and reference it? This no longer works…

GListener = PCIP.CreateDefaultSubobject<UElementalGestureListener>(this, TEXT("GestureListener"));

cannot convert from ‘TSubobjectPtrConstructor’ to ‘UElementalGestureListener *’

Haha I believe that’s fixed it!

So all I needed was UPROPERTY()!

I feel like such a noob now :wink: Thanks a lot for your help man, very much appreciated!

Looking at the code, TSubobjectPtr is just a wrapper around a raw C++ pointer, which means the garbage collector cannot know about. Try this instead:

UPROPERTY()
UElementalGestureListener* GListener;

GListener can now be tracked by the UObject sub-system.

Oh, I see, it’s an actual sub-object. In that case do this:

UPROPERTY()
TSubobjectPtr<class UElementalGestureListener> GListener;