UE 4.21 crash invalid memory access on game exit

Hello,

When I exit the game in editor mode, I get the crash due to invalid memory access from the core engine:


Access violation - code c0000005 (first/second chance not available)

UE4Editor_Engine!APawn::ConsumeMovementInputVector() [d:\build\++ue4\sync\engine\source\runtime\engine\private\pawn.cpp:629]
UE4Editor_Engine!APawn::UnPossessed() [d:\build\++ue4\sync\engine\source\runtime\engine\private\pawn.cpp:538]
UE4Editor_Engine!APlayerController::UnPossess() [d:\build\++ue4\sync\engine\source\runtime\engine\private\playercontroller.cpp:1231]
UE4Editor_Engine!APlayerController::Destroyed() [d:\build\++ue4\sync\engine\source\runtime\engine\private\playercontroller.cpp:1491]
UE4Editor_Engine!UWorld::DestroyActor() [d:\build\++ue4\sync\engine\source\runtime\engine\private\levelactor.cpp:592]
UE4Editor_Engine!AActor::Destroy() [d:\build\++ue4\sync\engine\source\runtime\engine\private\actor.cpp:3698]
UE4Editor_Engine!UGameInstance::RemoveLocalPlayer() [d:\build\++ue4\sync\engine\source\runtime\engine\private\gameinstance.cpp:674]
UE4Editor_Engine!UGameInstance::CleanupGameViewport() [d:\build\++ue4\sync\engine\source\runtime\engine\private\gameinstance.cpp:857]
UE4Editor_Engine!UEngine::CleanupGameViewport() [d:\build\++ue4\sync\engine\source\runtime\engine\private\unrealengine.cpp:2641]
UE4Editor_UnrealEd!UEditorEngine::EndPlayMap() [d:\build\++ue4\sync\engine\source\editor\unrealed\private\playlevel.cpp:282]
UE4Editor_UnrealEd!UEditorEngine::Tick() [d:\build\++ue4\sync\engine\source\editor\unrealed\private\editorengine.cpp:1992]
UE4Editor_UnrealEd!UUnrealEdEngine::Tick() [d:\build\++ue4\sync\engine\source\editor\unrealed\private\unrealedengine.cpp:403]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3699]
UE4Editor!GuardedMain() [d:\build\++ue4\sync\engine\source\runtime\launch\private\launch.cpp:174]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:145]
UE4Editor!WinMain() [d:\build\++ue4\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:276]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:283]
kernel32
ntdll

I’ve narrowed the issue down to a specific line, but it makes no sense to me why this is causing a crash everytime I exit play. I’ve reproduce the error in an incredibly simple example below.


class TEST_API AMyPawn : public APawn {
// add some boilerplate stuff here

AMyPawn() :  m_target(ForceInitToZero) { PrimaryActorTick.bCanEverTick = true; }

public:
   FVector m_target;

    void RecieveNewTarget(const FVector& _target) {
      // do some stuff here
       m_target.Set(10, 10, 10);   // <--- here is the culprit
       // do some more stuff here
    };

}

ReceiveNewTarget is called from MyPlayerController anytime a user clicks somewhere on the level i.e. something like this


void AMyPlayerController::SetTarget() {
    float x, y;
    this->GetMousePosition(x, y);
    FVector2D mouse_position(x, y);
    FHitResult hit_result;
    const bool trace_complex = false;
    if (this->GetHitResultAtScreenPosition(
        mouse_position, ECC_Visibility, trace_complex, hit_result)) {
        AMyPawn * pawn = static_cast<AMyPawn *>(this->GetPawn());
        if (pawn != nullptr && IsValid(pawn)) {
            pawn->RecieveNewTarget(hit_result.Location);
        }
    }
}

Out of curiosity i replaced the FVector m_target with a simple vector struct, but this still crashes. In fact, replace m_target with a class member of ANY type (int float, etc.), attempt to modify it, crash. It’s kind of concerning when simple C++ functionality behaves unreliably in the engine. It’s almost like this pawn was destroyed during the game tear-down by some thread, but then a different thread with it’s program counter currently in ReceiveNewTarget() is scheduled and then tries to access to m_target causing the seg fault.

Any help appreciated, thanks

Hi, I’ve seen this behavior in PIE. The workaround was to add an extra method to the game mode class


void AMyGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    Super::EndPlay(EndPlayReason);

    if (EndPlayReason == EEndPlayReason::EndPlayInEditor)
    {
         //Manually =nullptr some actors here
    }
}

@adludum AGameModeBase doesn’t have a “EndPlay” method to override…

I apologize for not being clear, this method belongs to Actor class


/** Overridable function called whenever this actor is being removed from a level */
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason);

Doesn’t work, still crashes.
I can’t believe a task so simple and commonly performed in game development causes an arbitrary crash in core engine code.

Somewhere in your code you have something holding a reference to some value created and destroyed in the body of a function.
The function goes out of scope, you keep a dangling pointer, in the chain of BeginDestroy() actions you reach undefined behavior and the engine crashes.

** we only see what you show in post, if you keep things out, we only guess.

There could be issue where your object goes out of scope and its memory gets free, check for a nullptr whenever you are calling SetDestination function. (Inside the SetTarget Func)

For anyone that cares: [USER=“434”]BrUnO XaVIeR[/USER] @Fieol

After hours of debugging, the fix was setting the Default Pawn Class to my proper pawn subclass in MyGameModeBase.
Simply having my pawn object in the World Outliner doesn’t suffice. GetPawn() indeed returns a non-null “valid” default pawn, but it wasn’t my subclassed pawn.

Somewhat comically, all of my debug prints aligned with what m_target should be, but each and every single access was seg fault. It just happened to get swallowed until the end.

No offense but your just regurgitating a seg fault definition (in a roundabout fashion).

The REAL issue was that I incorrectly assumed I was casting apples to apples with static_cast. UE’s Cast() would have caught the issue since it was actually a downcast.

You don’t even have to use the editor to set a pawn class, you can set them in GameMode class constructor. blahPawn::StaticClass()