Undefined Behaviour, Compiled Code

So I’ve came across something that looks like a bug from the compiler, but I’ve no idea how to fix it, specially the ue4 build systems leaves very little space to control the compilation.

I’m writing my custom Game instance class, I’ve created a Actor that calls the BeginPlay() from it’s own BeginPlay() (since the Game instance class doesn’t natively implement the BeginPlay() function:

void UBiscuitGameInstance::BeginPlay()
{
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join_Error);
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join);
}

So far so good, it get’s called and I thought it normal, when I got around to check how the program was running it it calls the fist instruction, then goes back to the start of the function and calls it again, then proceeding to the 2th instruction, I found that strange so I checked the Disassembly code that is shown as follows:

--- c:\flyingcookie\biscuit\source\biscuit\biscuitgameinstance.cpp -------------
}

void UBiscuitGameInstance::BeginPlay()
{
00007FFFCD9C7C40  mov         qword ptr [rsp+10h],rbx  
00007FFFCD9C7C45  push        rdi  
00007FFFCD9C7C46  sub         rsp,20h  
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join_Error);
00007FFFCD9C7C4A  mov         rax,qword ptr [rcx+208h]  
}

void UBiscuitGameInstance::BeginPlay()
{
00007FFFCD9C7C51  mov         rbx,rcx  
00007FFFCD9C7C54  xor         r8d,r8d  
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join_Error);
00007FFFCD9C7C57  mov         byte ptr [rsp+30h],0Eh  
00007FFFCD9C7C5C  test        rbx,rbx  
00007FFFCD9C7C5F  mov         rcx,qword ptr [rax+8]  
00007FFFCD9C7C63  lea         rdx,[rbx+1A8h]  
00007FFFCD9C7C6A  cmove       rdx,r8  
00007FFFCD9C7C6E  lea         r8,[rsp+30h]  
00007FFFCD9C7C73  mov         rax,qword ptr [rcx]  
00007FFFCD9C7C76  call        qword ptr [rax+10h]  
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join);
00007FFFCD9C7C79  mov         rax,qword ptr [rbx+208h]  
	ISFSPluginService.SubscribeEvents(this, SFSPluginInterface::RoomEventType::EventType_Room_Join);
00007FFFCD9C7C80  lea         r8,[rsp+30h]  
00007FFFCD9C7C85  mov         byte ptr [rsp+30h],0Dh  
00007FFFCD9C7C8A  lea         rdx,[rbx+1A8h]  
00007FFFCD9C7C91  mov         rcx,qword ptr [rax+8]  
00007FFFCD9C7C95  mov         rax,qword ptr [rcx]  
00007FFFCD9C7C98  call        qword ptr [rax+10h]  
}
00007FFFCD9C7C9B  mov         rbx,qword ptr [rsp+38h]  
00007FFFCD9C7CA0  add         rsp,20h  
00007FFFCD9C7CA4  pop         rdi  
00007FFFCD9C7CA5  ret  
--- No source file -------------------------------------------------------------

There is no reclusion in any of the functions, the SubscribeEvents() is being called successfully from other classes.

Within this class I’ve another similar error, original function:

void UBiscuitGameInstance::OnConnectSuccessfull() {

	//Check if the LoginMenu was already created and create it if not
	if (BiscuitLoginWidget == NULL) 
	{
		InitLoginMenu();
	}

	// Set it to visible 
	BiscuitLoginWidget->SetVisibility(ESlateVisibility::Visible);
	
}

Disassembly code:
— c:\flyingcookie\biscuit\source\biscuit\biscuitgameinstance.cpp -------------

void UBiscuitGameInstance::OnConnectSuccessfull() {
00007FFFCD9C8070  push        rbx  
00007FFFCD9C8072  sub         rsp,20h  

	//Check if the LoginMenu was already created and create it if not
	if (BiscuitLoginWidget == NULL) 
00007FFFCD9C8076  cmp         qword ptr [rcx+1D8h],0  
00007FFFCD9C807E  mov         rbx,rcx  
00007FFFCD9C8081  jne         UBiscuitGameInstance::OnConnectSuccessfull+18h (07FFFCD9C8088h)  
	{
		InitLoginMenu();
00007FFFCD9C8083  call        UBiscuitGameInstance::InitLoginMenu (07FFFCD9C7E60h)  
	}

	// Set it to visible 
	BiscuitLoginWidget->SetVisibility(ESlateVisibility::Visible);
00007FFFCD9C8088  mov         rcx,qword ptr [rbx+1D8h]  
00007FFFCD9C808F  xor         edx,edx  
00007FFFCD9C8091  mov         rax,qword ptr [rcx]  
	
}
00007FFFCD9C8094  add         rsp,20h  
00007FFFCD9C8098  pop         rbx  
	}

	// Set it to visible 
	BiscuitLoginWidget->SetVisibility(ESlateVisibility::Visible);
00007FFFCD9C8099  jmp         qword ptr [rax+2E0h]  
	// Set it to visible 
	BiscuitLoginWidget->SetVisibility(ESlateVisibility::Visible);
00007FFFCD9C80A0  mov         rcx,qword ptr [rcx+1D8h]  
00007FFFCD9C80A7  xor         edx,edx  
00007FFFCD9C80A9  mov         rax,qword ptr [rcx]  
00007FFFCD9C80AC  jmp         qword ptr [rax+2E0h]  
--- No source file -------------------------------------------------------------

So my question is does any one know if I did something wrong, or if not how I can try to fix this?

I also find it strange that this is only happening in this class, maybe it is treated differently by the compiler since it is so central to the game?

Note that the game instance does not crash.

A curious question, I have no solution, but if you throw in a checkNoReentry(); does it trigger without explicitly calling the same code twice, or through subsequent begin plays, etc.

So it seems to be fixed by now.

I ended up changing the implementation of the custom GameInstance class, so far as I understood, one can not use the overridden Init() function of the GameInstance class to create a custom Actor, as it will result in undefined behavior.

To note, the custom Actor was also having problems with the compilation even after being decoupled with the GameInstance class.

For any one trying to implement a BeginPlay and a Tick in a custom GameInstance class, I recommend calling the BeginPlay from any other Actor class you already have (I’m doing it form the GameMode).

The Tick is possible to set up a timer using the TimerManager that already exists in the GameInstance class.