Advertisement

C++ Function is crashing Unreal...not sure why

Started by September 04, 2017 10:04 AM
4 comments, last by MarcusAseth 7 years, 2 months ago

As the title says, the function below is crashing the Unreal Engine but I can't understand the reason...

I'm pretty sure that the first line is good.

But the variable "World" in the second  line, if I try to access a public variable of it (like GridHeight in the line below it), the engine immediately crash. I haven't the slightest idea of why... Any guess of what is happening? :/


void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	UWorld* World = Cast<UWorld>(WorldContextObject);
	AWormGameMode* GameMode = Cast<AWormGameMode>(World->GetAuthGameMode());
	if (GameMode->IsValidLowLevel())
	{
		int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
		int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
		int GridBlockSize = GameMode->GridBlockSize;
		------------------------------------------

		Row = -Location.Z / GridBlockSize + RowMiddleID;
		Column = Location.X / GridBlockSize + ColumnMiddleID;
	}
}

 

You aren't checking for whether GameMode is null. You need to do that, just in case it's not actually the type you expect it is, or it's not available yet. You're not checking World either.

If you aren't sure exactly where it crashes then you need to run the engine under the debugger. If you don't know how to do that, you might just be able to ask Visual Studio to attach to the Unreal process after it starts.

Advertisement
2 minutes ago, Kylotan said:

You aren't checking for whether GameMode is null. You need to do that, just in case it's not actually the type you expect it is, or it's not available yet. You're not checking World either.

You mean that IsValidLowLevel() is not doing what I thought it was doing? Documentation says "Checks to see if the object appears to be valid", I thought that "appears to be valid" included a check for nullpointers, and I realize now that it was probably a wild assumption :| 

Anyway, my new code below still crashes x_x

All I'm asking it to do inside the blueprint, is a PrintString of the returned Row and Column variables, so this is not some access violation in an array like the last time.

Since what is going wrong is not something obvious as I was hoping, I'll look into how to debug between Unreal & C++ then :P


void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	UWorld* World = Cast<UWorld>(WorldContextObject);
	AWormGameMode* GameMode = Cast<AWormGameMode>(World->GetAuthGameMode());
	if (GameMode != nullptr && GameMode->IsValidLowLevel())
	{
		int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
		int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
		int GridBlockSize = GameMode->GridBlockSize;
		------------------------------------------

		Row = -Location.Z / GridBlockSize + RowMiddleID;
		Column = Location.X / GridBlockSize + ColumnMiddleID;
	}
}

 

A member function called via a pointer requires the pointer to be valid to work. It turns out that the code does attempt to exit early and warn you if it's null, but this is not behaviour you should rely upon. You might find that it successfully finds the null pointers in debug mode but not release, for example.

And, again, you're still not checking the validity of the World.

And if GridBlockSize happens to be zero and the IDs are zero, it would crash.

12 minutes ago, Kylotan said:

And, again, you're still not checking the validity of the World.

That's it! :D

After that fix (code below) it works again, I was under the wrong impression that "UWorld* World = Cast<UWorld>(WorldContextObject);" was perfectly safe because it behaved properly on the second function...

Thanks for keeping up with my dumb mistakes ;)

Also thanks to @NajeNDa who spot it first, I added you a Thanks in the other topic. I had misunderstood what u said "Put checks or debug if World or GameMode are Nulls." I must have though that checking one was enough x_x

 


void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	UWorld* World = Cast<UWorld>(WorldContextObject);
	if (World != nullptr && World->IsValidLowLevel())
	{
		AWormGameMode* GameMode = Cast<AWormGameMode>(World->GetAuthGameMode());
		if (GameMode != nullptr && GameMode->IsValidLowLevel())
		{
			assert(GridBlockSize != 0);
			int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
			int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
			int GridBlockSize = GameMode->GridBlockSize;
			//------------------------------------------

			Row = -Location.Z / GridBlockSize + RowMiddleID;
			Column = Location.X / GridBlockSize + ColumnMiddleID;
		}
	}
}

 

This topic is closed to new replies.

Advertisement