Jump to content
  • Advertisement
MarcusAseth

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

Recommended Posts

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;
	}
}

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

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.

Share this post


Link to post
Share on other sites
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;
	}
}

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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;
		}
	}
}

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!