Tarray of struct access violation when adding a normal ustruct?

I tried searching and found https://answers.unrealengine.com/questions/361743/violation-error-on-add-to-tarray.html but this seems to not apply here? I am getting super confused here.

So I have “ScoreStructItem.h”
#include “CoreMinimal.h”
#include “ScoreStructItem.generated.h”

USTRUCT(BlueprintType)
struct FScoreStructItem
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	int32 Score;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FString DateTime;

	FScoreStructItem() {};
};

And I have a class extending “AGameModeBase”:

UPROPERTY(Category = Gameplay, VisibleAnywhere, BlueprintReadOnly)
USaveScore* ScoreInstance;

And finally I have “SaveScore.h” which has

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Basic)
TArray<FScoreStructItem> RecentScores;
void AddScore(int Score);

In my “SaveScore.cc” I have

void USaveScore::AddScore(int Score)
{
	FScoreStructItem ScoreStruct;
	FDateTime Today = FDateTime::Today();
	ScoreStruct.DateTime = FString::Printf(
		TEXT("%d-%d-%d"),
		Today.GetYear(),
		Today.GetMonth(),
		Today.GetDay());
	ScoreStruct.Score = Score;
	
	RecentScores.Add(ScoreStruct);
}

But whenever I call “AddScore(10)”, it crashes with the following message.

Access violation - code c0000005 (first/second chance not available)

Which points to my “RecentScores.Add(ScoreStruct);” as the cause.

I am very confused because I don’t even have pointers anywhere and as far as I understand, structs I can just pass by value in Unreal and it will create a copy for me that doesn’t go out of scope?

Any help I will be super grateful, thanks!

Edit
Here is the full stack

Access violation - code c0000005
(first/second chance not available)

UE4Editor_HigherPlaneSnake_5085!USaveScore::AddScore()
[c:\users\documents\unreal
projects\higherplanesnake\source\higherplanesnake\savescore.cpp:26]
UE4Editor_HigherPlaneSnake_5085!AHigherPlaneSnakeGameMode::StoreScore()
[c:\users\documents\unreal
projects\higherplanesnake\source\higherplanesnake\higherplanesnakegamemode.cpp:34]
UE4Editor_HigherPlaneSnake_5085!AHigherPlaneSnakePawn::GameOver()
[c:\users\documents\unreal
projects\higherplanesnake\source\higherplanesnake\higherplanesnakepawn.cpp:269]
UE4Editor_HigherPlaneSnake_5085!ASnakeSegment::OnOverlapBegin()
[c:\users\documents\unreal
projects\higherplanesnake\source\higherplanesnake\snakesegment.cpp:31]
UE4Editor_HigherPlaneSnake_5085!ASnakeSegment::execOnOverlapBegin()
[c:\users\documents\unreal
projects\higherplanesnake\source\higherplanesnake\snakesegment.h:13]

I don’t think it’s ScoreInstance is null because this is the code I have and check where the log doesn’t crash the engine:

ScoreInstance = LoadScore();
	
	if (ScoreInstance == NULL){
		ScoreInstance = Cast<USaveScore>(UGameplayStatics::CreateSaveGameObject(USaveScore::StaticClass()));
	}
	UE_LOG(LogTemp, Warning, TEXT("%s"), *ScoreInstance->SaveSlot);

Where LoadScore is

USaveScore * AHigherPlaneSnakeGameMode::LoadScore()
{
	return Cast<USaveScore>(UGameplayStatics::LoadGameFromSlot("DefaultSave", 0));
}

Can you provide full stack?

I guess ScoreInstance is null huh?

Sure, added more information at the bottom, thanks for taking a look!

Thanks for taking a look! I don’t think it’s a null instance though, as I have a check during constructor (which can be seen as new details above).

Hmmm try this->IsValidLowLevel() before Add to verify this, if its true it means everything is ok with the object and probably something is broken in array. Did you check log before crash happens? maybe there hints there

That was it!

But that’s super weird because I also added this:

ScoreInstance = LoadScore();
	
	if (ScoreInstance == NULL){
		ScoreInstance = Cast<USaveScore>(UGameplayStatics::CreateSaveGameObject(USaveScore::StaticClass()));
	}
	UE_LOG(LogTemp, Warning, TEXT("%s or %s"),
			(ScoreInstance == NULL) ? TEXT("true") : TEXT("false"),
			(ScoreInstance == nullptr) ? TEXT("true") : TEXT("false"));
	UE_LOG(LogTemp, Warning, TEXT("%s"), *ScoreInstance->SaveSlot);

but I got “false” and “false” for both meaning it’s actually not NULL or nullptr…

I also see “LogStreaming: Warning: Failed to read file ‘…’ error” which I assumed from UGameplayStatics::LoadGameFromSlot | Unreal Engine Documentation that it would return NULL but apparently not…?

I can now try and debug this, thank you very much for that super handy function “IsValidLowLevel”! :slight_smile:

Okay, so it was NULL for load and so it is going into the IF instance, it’s just being weird when I do CreateSaveGameObject… Interesting.

https://docs.unrealengine.com/latest/INT/Gameplay/SaveGame/Code/index.html shows me this is how I should create it but I guess this might be not working as I thought.

EDIT: 11/29/2017

Okay I found out the REAL reason as to why this was happening.

Turns out it wasn’t a problem of GameState or GameMode. Which makes sense since this is all local so one shouldn’t technically cause problem where clients don’t have access to gamemode.

The real reason behind it was because I was exposing my pointer via a UPROPERTY. What happens with this I think is that when the object is being initialized, it copies over the Blueprint defaults which is None, hence resetting my pointer. The reason why this didn’t happen when I switched over to GameState was because I made blueprint of GameMode and GameState was still in pure CPP format, meaning Blueprint defaults were not overriding anything.

I got around this via exposing the pointer via a function and not exposing it as a visible property elsewhere.

For more information, they go through it in more lengthy detail here: UPROPERTY member vars reset to NULL by ObjectInitializer - C++ Programming - Unreal Engine Forums

--------------------------------- Wrong explanation from11/28 - keeping for context

Okay, so turned out this had nothing to do with TArray of structs… Writing my response here in case anyone has same problem in the future.

I still don’t really understand what’s going on but here are my findings.

It turns out that the GameMode that is constructed at the beginning which logs the construction success is NOT THE SAME GameMode that I get via

AHigherPlaneSnakeGameMode* GameMode = Cast<AHigherPlaneSnakeGameMode>(GetWorld()->GetAuthGameMode());

from my Pawn.

I solved this by creating my GameState that has the exact same fields, constructor, and functions.

From what I understand GameMode is only available on Server side. However I am not sure how this applies here… but everything is fixed with GameState in my case.