まっそのせかい

やった事のメモとか

DXライブラリ使用時に終了後もプロセスが残る問題

事の始まり

DXライブラリを用いて通信(チャットプログラム)を試していたら、突然エラーが出るようになった。

f:id:massoumen:20170422190305p:plain

exeを起動しっぱなしの状態で実行すると出てくるエラーだが、今回はちゃんと終了させてから再び実行したはず…
そこで、 タスクマネージャで調べてみると…

f:id:massoumen:20170422190524p:plain

あれ、バックグラウンドでプロセスが残ってる…?(Chat.exeが試してるプログラム)

こいつを終了してやるとエラーが消えたので、やはり原因はこいつが残っている事にある。
しかし、なぜ残っていたのだろうか…

f:id:massoumen:20170422192419p:plain

exeを直接実行しては終了を繰り返すとエライ事に

調べてみたところ、恐らくProcessMessage()やDxLib_End()を適切に実行するようなプログラムを書けていないのが原因である。

ダメなパターン

プロセスが残ってしまう今回のパターンでは次のようなコードを書いた。

#include <DxLib.h>

//省略(他のインクルードやグローバル変数)

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //省略(初期化やウィンドウサイズの設定など)

    //ZキーかXキーの入力があるまでループ(入力の受け付け)
    while (GetKey(KEY_INPUT_Z) == 0 && GetKey(KEY_INPUT_X) == 0) {
        KeyUpdate();
    }

    //省略(他の処理)

    DxLib_End();

    return 0;
}

大部分を省略してしまったが、GetKey関数とKeyUpdate関数は自作関数で、それぞれキーの状態とキーの入力状態の更新を行う自作の関数だ。
このような無限ループを用意してしまうと、もし入力の受け付け部分の無限ループでウインドウ右上の×を押した際に、恐らくDxLib_End関数まで処理が進まない。
もっと言えばDXライブラリではProcessMessage関数を毎フレーム実行するようにしないといけない(詳しくは知らないが、そうしないと正しく動かない可能性がある)らしいので、その点も悪いと考えられる。
恐らくDXライブラリを用いるプログラムとしては0点である。

(多分)大丈夫なパターン

要するに、DXライブラリを用いる際は

  • ループの時にProcessMessage関数を毎フレーム実行する
  • 最終的にDxLib_End()を実行する

という事に気を付ければいいんだと思う。(多分)

てなわけで早速修正。

#include <DxLib.h>

//省略(他のインクルードやグローバル変数)

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //省略(初期化やウィンドウサイズの設定など)

    //ZキーかXキーの入力があるまでループ(入力の受け付け)
    while (ProcessMessage() == 0) {
        if (GetKey(KEY_INPUT_Z) == 0 && GetKey(KEY_INPUT_X) == 0) {
            KeyUpdate();
        }
        else {
            break;
        }
    }

    //省略(他の処理)

    DxLib_End();

    return 0;
}

キー入力など毎フレーム受け付けるタイプのものを利用する時はProcessMessage関数を実行する。
こうやって書く事で×ボタンでウインドウが閉じられた際にProcessMessage関数が0以外を返すので、無限ループを抜けDxLib_End関数を実行して終了してくれるはず。

このように書き直したところ、終了後にプロセスが残ってなかったので多分これでいいと思う。
用いるライブラリの仕様は最低限把握しておこう。