[UE4] パッケージアプリの起動直後からデバッガをアタッチする


検証Ver:4.25.0

ケース

 極々稀ですが「起動直後のパッケージアプリにアタッチしたい」ことがあります。主に以下の問題に遭遇した場合です。

・Visual Studioから起動した時には問題が発生しないのにパッケージだけ問題が発生する
・アプリケーションが起動直後に問題が発生するのでログも何も出力されずヒントが無い
・パッケージにプロセスアタッチしたいけどクラッシュするタイミングの方が早いので間に合わない

もう少し具体的には以下のようなケースが該当します。

・アプリケーション起動直後に理由不明の強制終了が発生する
 → プラグインの読み込み失敗、アセットの破損など

・アプリケーション起動直後のデバッグ
 → パッチのマウント、初回ロードなど

起動時引数で解決

 -WaitForDebuggerのコンソールコマンドをアプリケーション起動時引数に渡すことで、デバッガがアタッチ(Visual Studioからプロセスアタッチ)するまでアプリケーションがSleepで待機させておくことができます。ソース上ではEngineLoopのPreInit()で以下のようにプロセスアタッチが発生するまで待機します。これを使えばアプリ内にディレイを仕込む必要が無くなるので良いですね。

#if !UE_BUILD_SHIPPING
    if (FParse::Param(FCommandLine::Get(), TEXT("WaitForDebugger")))
    {
        while(!FPlatformMisc::IsDebuggerPresent())
        {
            FPlatformMisc::LowLevelOutputDebugString(TEXT("Waiting for debugger...\n"));
            FPlatformProcess::Sleep(1.f);
        }
        FPlatformMisc::LowLevelOutputDebugString(TEXT("Debugger attached.\n"));
    }
#endif

 あとはVisual Studioから[Debug]->[Attach To Process]を選択して、

 実行中のアプリケーションを選択してAttachすることで、アプリケーションのウィンドウを開いて進行します。

 プロセスアタッチするまではアプリケーションウィンドウが開かれていない状態のため、アタッチし忘れるとずっとバックグラウンドで動いたままとなります。アプリのアタッチし忘れにはご注意ください。

おまけ

 起動引数には様々なものが存在していて、公式ドキュメントの「コマンドライン引数」でも確認することができます。
他にも色々ありますが、ドキュメントに無い項目としては以下のようなものもありますのでデバッグ時などに役立てて下さい。

-CleanLogs
 ログ用フォルダがある場合削除します。ログファイルが貯まり続けるのを抑制するのに役立ちます。

-CleanScreenshots
 スクリーンショット用フォルダがある場合削除します。上記同様にスクリーンショットが蓄積するのを抑制できます。

-ExecCmds (-execcmds="stat unit, stat memory")
 起動直後から対象のコンソールコマンドを実行することができます(複数のコマンドを指定することも可能です)。