[4.10.1] TQueue incorrectly destroyed if stored in TArray (+ memory corruption)

Put the following code into your gamemode’s declaration:

TArray<TQueue<int32>> TestArray;

Then in StartPlay() or BeginPlay() or similar, in the gamemode’s .cpp file:

TestArray.Add(TQueue<int32>());

When the gamemode is destroyed, and tries to empty the TArray, the TQueue’s destructor will not behave as expected - even though there is nothing inside the TQueue itself, the destructor will attempt to not only delete the original singular TNode*, but will somehow continue on deleting memory until a crash occurs. I’ve had this corrupt memory in other parts of UE4 before, but it mostly just crashes on ‘Tail = Tail->NextNode;’ -

/** Destructor. */
	~TQueue()
	{
		while (Tail != nullptr)
		{
			TNode* Node = Tail;
			Tail = Tail->NextNode;

			delete Node;
		}
	}

Note: this problem does not occur if using

TArray<TQueue<int32>*> TestArray, 

and

TestArray.Add(new TQueue<int32>())

If testing this, one must obviously manually ‘delete’ this new-ed memory in the gamemode’s EndPlay() or it’s an unfair comparison. Still, doing it that way yields 0 issues, so something’s going wrong when the TArray itself destroys the TQueue element(s).

All testing performed via starting PIE and then stopping it.

Thanks!

Theory from the Slack group:

Lyan [1:15 AM] @ think I may
have got it, Add in TArray calls the
copy constructor by default, TQueue
has none defined so it will use a
compiler generated one which probably
just copies the member Tail pointer to
the copy residing in the array.
however, when the queue leaves the
scope of the function where you call
add, the temporary queue’s destructor
is called and destroyed Tail, but Tail
is still being pointed to by the queue
in your array

I’ve added a pull request to fix this via adding a copy constructor to TQueue.

https://github.com/EpicGames/UnrealEngine/pull/2203