EXCEPTION_ACCESS_VIOLATION when accessing TArray?

I have a TArray of pointers to objects:

TArray Modules;

In my class constructor, I do:

Modules.Reset();

Since from what I can glean by looking at sample code, this is a reasonably safe way to initialize/zero-out the array. At some point right after level start, I add a single element to the array. So, it should at least have length 1. Then some point later on (1 second later actually, via timer), I execute the following code:

UModule* ASagittarius::GetModule(FString ID)
{
	int32 i = 0;
	bool found = false;

	LogDebug(FString::Printf(TEXT("Number of currently loaded modules: %d"), Modules.Num()));
	for (i = 0; i < Modules.Num(); i++)
	{
		if (Modules[i]->ID == ID)
		{
			found = true;
			break;
		}
	}
	if (!found)
	{
		LogWarn(FString::Printf(TEXT("GetModule() - module with ID %s does not exist"), *ID));
		return NULL;
	}
	return Modules[i];
}

But I always get an EXCEPTION_ACCESS_VIOLATION whenever I call Modules.Num(). I have been over the code dozens of times now and can’t catch what I did wrong, and furthermore this is the same idea employed in several places in ShooterGame.

My array should have an element in it (only I don’t know if it does, since Num() errors out). So what is going on here?

EDIT: Here’s the entire contents of Module.h which defines the “UModule” class:

// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "SagResponse.h"
#include "Sagittarius.h"
#include "Module.generated.h"

/**
 * 
 */
UCLASS(Abstract)
class UModule : public UObject
{
	GENERATED_UCLASS_BODY()

	FString ID;
	ASagittarius* Parent;

public:
	virtual void Initialize(ASagittarius* NewParent);
	void SubmitAction(FString QueryID, UAction* ToSubmit);
	virtual void OnResponseReceived(FString ActionID, USagResponse* resp);
};

Please note that even though the class is abstract, pointers to its various subclasses are what is actually getting stored in the array. They are then dynamically cast back when returned from the GetModule() function.

EDIT 2: Header for Sagittarius.h, where the array is defined:

// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Sagittarius.generated.h"

// Other stuff (omitted for brevity)

/**
 * 
 */
UCLASS()
class ASagittarius : public AActor
{
	GENERATED_UCLASS_BODY()

	USagittariusLinkClient* Link;
	FString SagPass;
	TArray Modules;

public:
	void Initialize(FString AppID, FString Pass);
	UAction* CreateAction(FString Type);

	void RegisterModule(UModule* m);
	UModule* GetModule(FString ID);

	// Other functions...(omitted for brevity)

};

Instead of using .Reset()

I recommend that you use .Empty()

Modules.Empty();

That releases all the memory for the dynamic array but is quite stable for re-adding new entries

I use .Empty() between savings/loadings on my arbitrary binary array which I use to compress and save to / load from disk repeatedly,

supplying variable amount of info each time,

so I have very vigorously tested .Empty() and it is very stable!

If your problem persists then something else is going on that I can help with if you provide more code

:heart:

Rama

What happens if you do not call .Empty() at all during the constructor phase?

if you just remove that for now?

Does the error still occur?

Rama

Error occurs without any initializing in constructor, with .Empty() in constructor, and with .Reset() in constructor. I emailed you all the code so you can get a better look at it.

what happens if you do a test and comment out most of your code

and use

//test
TArray Modules;

with the rest of your current code structure, including the .Empty() and the .Num()

perhaps the fact that your type is UModule* is causing some troubles

:slight_smile:

Rama

Haha…same error. So at least it’s not the datatype.

well that is very clarifying

Let’s stick with FString till we get this fixed, okay?

Simplifies my mental debugging enormously

how are you defining your global Modules variable?

Please show the whole .h

:slight_smile:

Rama

we’ve already identified that UModule is not the source of the issue here

I would like the .h file for where you are declaring the variable “modules” that we are currently testing with FString instead of UModule*

//using <> is really hard in this text system without code, and single lines of code get rid of the <>

//code
 TArray Modules;

the entire .h and the .cpp for your use of Modules please :slight_smile:

Are you absolutely sure its the .Num() and not your accessing of the pointer data after that point?

the errors are not always accurate to line number

please comment out all code

except the .num()

again, to clarify,

when you get chance:

  1. comment out all your code except the .Num(), keeping the .empty() too

  2. and using array of FStrings for “Modules”

I should think it IMPOSSIBLE for you to get a error this way

make sure all other code utilizing the UModule* is also commented out


my prediction = it has something to do with your pointers not the .Num() and the call stack line number is not showing that

Rama

PS: translation = you are not the only one finding this behavior very strange and hard to fathom, hope that helps you feel better :slight_smile:

So…it turns out the issue wasn’t on that line. Or that class. Or any other class in the stack trace. It was an uninitialized pointer in the UMOTDModule class (yeah, pointers again…), which avalanched into a bunch of things that eventually caused the exception.