読者です 読者をやめる 読者になる 読者になる

DirectX Graphics フルスクリーンモードと窓使いの憂鬱

DirectX

(2009年10月27日追記) 以下の問題は,ゲーム側のウィンドウリークとの複合問題であることが分かりました.『窓使いの憂鬱』単独の問題ではなかったことをお詫び申し上げます.
詳細については『http://d.hatena.ne.jp/NyaRuRu/20091026/p1:title=』をご覧ください.



サークルで作成しているゲームについて「フルスクリーン環境で実行した後にゲームを終了すると一般保護違反が発生する」という症状が報告されて,色々調べてみたところ原因は『窓使いの憂鬱』にありました.どおりでこちらの環境で再現しなかったわけです.実際『窓使いの憂鬱 Ver.3.30』を常駐させることで問題を再現できることを確認しました.
多くの場合こういう現象は「相性問題」という便利な言葉で真実に蓋をされてしまいがちですが…たまには「解」でもご覧あれ.


クラッシュ時のスタックトレースはこんな感じ.

user32.dll!_InternalCallWinProc@20()  + 0x28
user32.dll!_UserCallWinProcCheckWow@32()  + 0xb7
user32.dll!_DispatchClientMessage@20()  + 0x4d
user32.dll!___fnDWORD@4()  + 0x24
ntdll.dll!_KiUserCallbackDispatcher@12()  + 0x13
user32.dll!_NtUserMessageCall@28()  + 0xc
user32.dll!_SendMessageTimeoutW@28()  + 0x21
mayu.dll!notify()  + 0xf5
ntdll.dll!_LdrpCallInitRoutine@16()  + 0x14
ntdll.dll!_LdrShutdownProcess@0()  + 0x142
kernel32.dll!__ExitProcess@4()  + 0x42
kernel32.dll!7c81cab6()
test.exe!__crtExitProcess(int status=0)
test.exe!doexit(int code=0, int quick=0, int retcaller=6614773)
test.exe!exit(int code=0)
test.exe!WinMainCRTStartup()
test.exe!WinMainCRTStartup()

これ見た時点で「むぅ」だったんですが,一応ソースコードもチェックしてこれが意図的な挙動 (つまりバグ) であることを確認.
というわけで DllMain から user32.dll の API 呼び出しちゃまずいです.ちょうど例の後ろ向きな記事 (id:NyaRuRu:20051220#p2) でも取り上げた直後なのでなおさらげんなりと.興味がある方は「コラム9 プロセス終了処理とDLL_PROCESS_DETACH」で参考資料として挙げたリンクを色々漁ってみると面白いかと思います.
なぜフルスクリーンモードの時だけ問題が表面化するかについてもコラム1つ分ぐらいの話が書けそうなのですが,これはまあまた今度.