Doing a FQuat*FQuat when one of them is a parameter-by-value in non-debug builds causes access violation

static FRotator GetConversionRotator()
{
const auto mineToUE4 = FRotator::MakeFromEuler(FVector(-90,0,90));
return mineToUE4;
}

FQuat ConvertToUe4Rotation(FQuat inputQuat)
{
	const FQuat rotQuat = FQuat(GetConversionRotator());
	const FQuat newQuat = inputQuat * rotQuat;
	return newQuat;
}

then just call it like this

FQuat xformRot = FQuat::Identity;
//...populate xformRot here maybe
xformRot = ConvertToUe4Rotation(xformRot);

The line const FQuat newQuat = inputQuat * rotQuat; will access violate on non-debug builds.
Debug builds are fine, and changing inputQuat to be const FQuat& works around the issue.

Win64 Development Editor 4.5.1 github 4.5 branch commit ad6f983017ba127247a9fbbbae10056211cff0af
compiled with vs2013 update 3

This is the assembly instruction that’s generating the exception:

		const FQuat newQuat = inputQuat * rotQuat;
00007FF84FF81A15  movaps      xmm3,xmmword ptr [rbx]  

From what I can tell, the issue is the use of movaps here, which expects aligned operands.
Byte patching/hex editing this instruction to movups (the unaligned variant) fixes the issue, which would seem to indicate an alignment problem, but using __declspec(align) to try to force the alignment doesn’t seem to help. Perhaps one of Epic’s engineers can investigate further on this basis.

Hey rajkosto-

What is the parent class where your functions are declared and where are you making the call from? Also, could you post the exact error message you receive when you try running the code in a non-debug configuration?

Cheers

It doesn’t matter where it gets called from. Also they were static functions so it’s equivalent to the free-functions I wrote above. Maybe them being a member function (__thiscall) would make the bug not appear. The error i get is “Access violation reading location 0xFFFFFFFF”

I ask because I’m trying to reproduce the same thing you’re seeing and want to make sure that my setup matches yours. Knowing how you set everything up would help me understand the exact nature of the bug and what might be the cause.

It was in a PostLoad of an Asset Type i’ve made (UObject derived)
I bet it would work from anywhere, so, to test, put it in your game mode or something, just call the free functions from any member function.
Twiddle reproduced it with no issues as you can see.

Here’s a really simple code project that reproduces the error when built alongside the current Github 4.5.1 source:
zipped project via dropbox

I just placed the code from the OP into the GameMode, calling it in the GameMode’s constructor.

Looks like the assembly mnemonic I mentioned above is an SSE instruction, hence why it would only show up in an non-debug build (I’m presuming that debug builds don’t use SSE).

Hey Guys-

Thank you for submitting the project. I was able to reproduce the problem that you are both seeing. I have submitted it our internal tracking system (UE-5027) for further investigation.

As a side note, if you create a new FQuat variable inside the ConverToUe4Rotation function and set it equal to the inputQuat parameter you can then use the new variable in place of inputQuat in your multiplication and build the project successfully.

Cheers

Thanks for confirming the repro, .
When you’ve confirmed what the issue was, and have a fix, would you mind posting here again? I’d be curious to know if I was correct about the SSE/alignment issue, and if so, how you’ve resolved it.

#Same or Highly Related Crash

I have the same or a highly related crash over here that Epic has not yet responded to.

It involves sending an FQuat over the network without setting it to a local variable first.

:heart:

PS: trying to add to the discussion, not take focus away from’s issue.

If you want to investigate this for similarities, , you could debug a release build of your issue, and look at the assembly line that the crash occurs on. Easy way to verify if it is an alignment issue, would be to confirm that the crash occurs on a movaps instruction like this one does, and then hotpatch that to movups instead, and see if the crash goes away…
Otherwise, want to post a minimal sample for repro on your question, and I’ll try to see what I can spot?

Hi all,

twiddle’s diagnosis of the problem is correct in that it’s an alignment issue. The compiler is copying FQuat::Identity into an unaligned temporary on the stack (because you’re passing by value) using movups, then the code inside ConvertToUe4Rotation is reading it using movaps.

This appears to be a problem with DLL-imported statics, as a module-local static (i.e. not DLL-imported) doesn’t exhibit this problem. Other ways to work around the problem:

  • Pass the FQuat by reference, not by value, avoiding the temporary.
  • Put the code in a function and call the function instead.
  • Add a static FQuat::GetIdentity() function are call that instead of referencing the static member directly.

We believe it’s a VC code generation problem and are trying to reproduce a minimal example in a standalone C++ project to report to Microsoft’s compile team. For now, we suggest passing by reference instead of by value, as passing aligned types by value has issues on 32-bit platforms anyway.

Steve

Hi Steve,

We had that issue using Unreal 4.8 in a 64-bit Windows platform, have you had any news from Microsoft yet?
So far the solution is using a const ref instead of passing the FQuat by-value and it works,

Thank you!
Rem

Hey

There has not been a confirmation where the core of this issue lies yet. If you’ve found a solution that works for you I would continue using that for the time being.

I have bumped into this exact FQuat alignment issue through versions 4.16-4.20 on VS 2015 and 2017. I can mostly work around the issue with the above suggestions, but I’m wondering if this ever crops up for the Epic team and if there is a “better” fix?

Where it seems to happen more frequently than just “straight” C++ code is:

  • When a BP construction script calls C++ code (not 100%, but frequent)
  • When a cook runs, outside of BP construction scripts

These are both crash situations where it can be harder to track down an FQuat misalignment - and more importantly these crashes can often elude localized testing prior to checkins.

thanks,
jeff