Access violation with input component

Hi,

So have an input component that I set up in a player controller class:

void ASimulationController::setupInput()
{
	EnableInput(this);
	InputComponent = ConstructObject<UInputComponent>(UInputComponent::StaticClass(), this);
	check(InputComponent);
	InputComponent->BindAction("GoalSeek", IE_Released, this, &ASimulationController::keyPressG);
}

I then call a method from another class in the keyPressG method:

void ASimulationController::keyPressG()
{
	accessStuff->SetGoalSeekingState();
	UE_LOG(LogTemp, Log, TEXT("Goal seeking state changed"));
}

I then try to change a boolean variable ‘goalSeeking’ in the method of that class:

void ABoidManagement::SetGoalSeekingState()
{
	goalSeeking = !goalSeeking;
	UE_LOG(LogTemp, Log, TEXT("I made it here for some reason"));
}

When I comment out the line ‘goalSeeking = !goalSeeking’, the everything works and the text prints to the output log fine (every time that the G key is pressed). However, with this one line in, I get an access violation when I press the G key.

It doesn’t seem to be a problem with refering to another class method as the text prints fine in the output log. The access violation is:

Unhandled exception at 0x00007FFD280A70C4 (UE4Editor-TestBoids.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0x0000000000000420.

Do you use goalSeeking as consdition somehwere? The real issue might be there.
Also look up the stack dump in logs, it shows exacly where the crash happens to make it easier run VS debug when crash happens VS will point you to faulty code automatically. By way you ask this quastion seem you not aware of that, as you code with C++ be prepared that you need to deal with crashes too, because if something goes wrong in execution of your code it will crash like that.

Access valuation happens when you calling function on null (pointing to 0 memory address) or invalid pointer (pointing to unallocated memory, because object there was destroyed, this should not happen in variables with UPROPERTY()) .

I’ve already looked at the stack dump, that’s how I found out where the error was - as I explained in my question. I know where the error is just not why it is occurring. I would prepare for crashes if I knew what was crashing it! I know why access violations occur, I just can’t see any problems in my code causing it.

My goalSeeking boolean is a UPROPERTY variable.

Hey CosmosD-

Can you let me know if using the following extended form gives the same error?

if (goalSeeking)
{
	goalSeeking = false;
}
else
{
	goalSeeking = true;
}

If you do still have the same error, can you post the full callstack as well as the log files from the crash for additional information?

Cheers

Hi ,

Unfortunately that did not help. This is what I get from the crash reporter:

I couldn’t find the log files.

I have tried using a different method of initializing the input component which checks if it is null and then if it is not, it calls the SetGoalSeekingState method.

So I have pretty much deduced from this that I am not doing something right when it comes to setting up the input component.

void AInputController::SetupInputComponent()
{
	EnableInput(this);
	Super::SetupInputComponent();
	InputComponent = ConstructObject<UInputComponent>(UInputComponent::StaticClass(), this);
	check(InputComponent);
	InputComponent->BindAction("GoalSeek", IE_Released, this, &AInputController::keyPressG);
}

void AInputController::keyPressG() 
{
	auto changeState = Cast<ABoidManagement>(this);
	if (changeState)
	{
		changeState->SetGoalSeekingState();
		UE_LOG(LogTemp, Log, TEXT("Goal seeking state changed"));
	}
	else
		UE_LOG(LogTemp, Log, TEXT("Error happened"));
}

In the if else clause for checking the validity of the changeState object, only the else executes.

And the call stack in Visual Studio:

Hey CosmosD-

Looking at the code for APawn::CreatePlayerInputComponent(), rather than using ConstructObject for the input component it uses NewObject(this, InputComponentName); where InputComponentName is a static const FName variable. If the class you are working in inherits from ACharacter or APawn then this should already be invoked. In that case, as shown in the third person template code for the character, you can use the overridden function SetupPlayerInputComponent to simply bind your actions without having to setup the component itself again.

Hi ,

Unfortunately, the class that uses the goalSeeking variable is an Actor class.

Just fyi, I create a object of my class (with the methods I want to call) and check it like this:

    auto changeState = Cast<ABoidManagement>(this);
	if (changeState)
	{
		changeState->SetGoalSeekingState();
		UE_LOG(LogTemp, Log, TEXT("Goal seeking state changed"));
	}
	else
		UE_LOG(LogTemp, Log, TEXT("Error happened"));

I have not been able to reproduce the crash on my end. Would it be possible for you to share your project where you are experiencing this crash? If you’re able to zip the project folder you can attach it here or upload the project to google drive or Dropbox and then send me a private message on the forums with a download link rather than sharing it publicly.

Hi ,

I have sent you a private message with my project in.

Thanks in advance

I opened the project you sent and when I press G there was no crash. I noticed in the output log that I was getting an “error happened” message when I pressed the button. Looking at the code, it appears that the cast occurring at the beginning of the keyPressG function is failing so I am never entering the if statement. This would be expected since the ‘this’ being used is an AInputController being cast to ABoidManagement.

If you remove/comment out the line changeState->SetGoalSeekingState(); and run the game, which of the log messages do you see in your output window?

Yes I modified my code as I found that using the if else would prevent the crash from happening so I didn’t have to keep reloading my project.

I am unsure of the exact syntax to use for the cast, so that could be where the error is. With that line commented out, the same message ‘Error happened’ appears on the output log.

Something that may help you is to rework your input component settings. Rather than having the input component bind to a function that is only used to call another function, you can instead bind the input component directly to the second function. So instead of:

InputComponent->BindAction(“GoalSeek”, IE_Released, this, &ASimulationController::keyPressG);

you can instead use:

InputComponent->BindAction(“GoalSeek”, IE_Released, this, &ABoidManagement::SetGoalSeekingState);

If that still causes a crash for you, please explain exactly what you are trying to accomplish to help me understand what is happening.

I have tried to change my code as you suggested, however I get this error:

I did try doing your solution before I posted on the forums but I think I abandoned that idea as I got this error.

To put it in simple terms in case I have confused you, all I want is the state of a boolean variable to change (toggle) when I press a key on the keyboard.

Hey CosmosD-

I believe I have found the issue. Looking back at the code from your original post, when you call accessStuff->SetGoalSeekingState(); the accessStuff is not set to any instance of the ABoidManagement class. So when it tries to access the class it is reading a null pointer and then crashing.

It is till possible to do what you’re intending, however the setup is slightly different. First I setup my input component to the following function:

void AMyProjectCharacter::UpdateActorBool()
{
	TArray<AActor*> Whatever;
	UGameplayStatics::GetAllActorsOfClass((), AMyActor::StaticClass(), Whatever);

	for (AActor* TActor : Whatever)
	{
		AMyActor* MyActor = Cast<AMyActor>(TActor);
		if (MyActor)
		{
			MyActor->UpdateBool();
		}
	}
}

This function is setup to search the level for all instances of MyActor (or child blueprints) and add them to an array. It then cycles through the array and, for each element found (in my test I only had one instance in the level), will cast to AMyActor to ensure the array element is of the correct class. If the cast succeeds, it then calls the UpdateBool() function for that specific instance which uses the same syntax you used (MyBool = !MyBool) to change the value of the local boolean. Hopefully this helps with your setup as well.

Cheers

Hi , thank you very much for this solution. Would I change any instances of AActor to the name of my Actor class? My actor class being named ABoidManagement.

In this case you would change instances of AMyActor to your actor class.