フリーゲーム・フリーソフトの開発過程を記録していく、TDtechnic公式ブログです。製品はカテゴリの「ダウンロード場」からダウンロードして頂けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

こんにちは。今更ながら不死女が開発予定のままになってたので直しておきました。

今回はですね…非常に面倒なバグに逢いました。何より解決の障害となったのは、どちらも「情報が全くない!」ということです。

バグ① DirectShowがどうあがいても絶望
DirectShowを使いたければまあとりあえずDShow.hをインクルードしますよね。ところが!この時点で、str系の関数とwcs系の関数に対して「名前が避けられた #pragma として記述されています。」の嵐になりました。そして、本当に困ったのはここからです。このエラー名で検索すると、一応扱っているサイトはありました。しかし、それらの例ではどれもウォーニングとして出ているためコンパイルに支障はなく、どうしても消したければ「#pragma warning(disable:4995)」や「#include <iostream>」を記述しろとのことでした。

ちょっと待って下さいよ。私の環境(Windows7+VS2012+Microsoft SDKs\Windows\v7.1A\include\DShow.h)だと、ウォーニングじゃなくてエラーで出るため、コンパイルすら通りません。しかも上記の方法がどれも効きません。

工エエェェ(´д`)ェェエエ工

となった私は、上記のような解決策を探るのをやめて、DShow.hを自分で覗いてみることにしました。明らかに原因はこいつなので、必要とあらばちょっと書き換えてやろうと思ったのです。

でも、その必要はありませんでした。幸いなことに、DShow.hの最初の方に怪しい記述がありました。

#ifndef NO_DSHOW_STRSAFE
#define NO_SHLWAPI_STRFCNS
#include <strsafe.h>
#endif

出ているエラーの対象はどれもCの文字列系関数ばかりなので、それらの安全性に関わる問題でしょう。STRSAFEとかいかにもじゃないですか。この4行を見る限り、NO_DSHOW_STRSAFEを定義すれば安全性を無視してくれそうですね。早速DShow.hの前で#defineしてみました。

========== すべてリビルド: 3 正常終了、0 失敗、0 スキップ ==========

ざまああああああああああああ!iostreamだのintrin.hだのは関係ないんだよ!本質的に解決するにはNO_DSHOW_STRSAFEを定義すればいいんだ!

気になってNO_DSHOW_STRSAFEでググってみました。英語なら、私と同じような主張してる方もいらっしゃいますね。ところがどうでしょう。日本語サイトでこの方法を書いている人が誰一人いないんですが。え?当たり前だったの?それとも私が日本人初の発見者なの?まあどっちでもいいや。とにかく不死女がコンパイルできるようになったんだから。

そこのMicrosoftのあなた!DirectShowを使わないのが正解とか言わないの!

バグ② thisがnull!?
さて、DirectShowと仲良くなったところで、ちょいとIMEクラスの改造をしました。今まではIMEクラス専用のコールバック関数があって、ウィンドウプロシージャにそれを指定することでIME処理を噛ませていました。しかし、DirectShowもコールバックに組み込む必要が出てきまして、同じ方法を採ってしまうとIME用プロシージャとDirectShow用プロシージャのどちらかしか指定できず、共存できなくなってしまうのです。

ではちょっと方針を変えましょう。まずウィンドウプロシージャとしてコールバック関数を一つだけ作ります。そしてそこからメッセージに応じて各クラスメソッドを呼びましょう。やってることは本質的に変わらないのでこの仕様変更が問題になるとは夢にも思いませんでした。

ところがここからが悪夢なのですよ。IMEクラスはシングルトンなので、Getメソッドが初めて呼ばれた時にnewされます。で、そのタイミングは、前の仕様なら「初めてメッセージループが回った時」(IME用のプロシージャを毎回呼ぶため)でしたが、仕様変更後は、「初めてIME系のメッセージが来た時」(それ以外のメッセージの時は呼ばれないため)となります。まあでも初期化タイミングが違うだけですから、正しい初期化さえしていれば問題にならないはず…でした。

するとどうでしょう。何故か頻繁にアクセス違反を起こします。最初はどうせ文字列系で溢れてるんだろうと思って文字列メンバ変数ばかり調べていたのですが、不思議なことに、メンバ関数内でメンバ変数のどれにアクセスしても違反になるではありませんか!その後の調べで、なんとthisがヌルポインタになっているとわかりました。

ちょっと待って下さいよ。thisがnullになるなんて聞いたことないぞ。そもそもインスタンスへのポインタがnullなのに、なんでメンバ関数が呼び出せるんだよ!しかも、インスタンスが割り付けられないなら例外を投げるだろ普通!nothrowにしてるわけでもないのに、何でnullを返すんだ。しかも、初期化時にMessageBoxなどを呼び出すとなぜか発生しなくなったりして、謎は深まるばかりです。もちろんググってもthisがnullになる事例なんて出てきません。

結局私には本質的な原因はわかりませんでした。ただ、「コールバック関数内でインスタンスを初期化し、それをすぐに使おうとした」という条件の時にnewがnullを返すようだとわかったので、初期化を別の場所で行うようにしたところ一切発生しなくなりました。newするタイミングと、newしてから使うまでの時間が関わるということは随分と低レベルな部分の問題っぽいです。newの仕様ですかね。解決策としては「newは落ち着いてやりなさい」としか言いようがありません。ちょっと残念ですがこれが私の結論です。

いかがだったでしょうか。どちらもゲームプログラマーなら遭遇し得るバグじゃないでしょうか。google検索の件は私が調べ足りないのもあるかと思いますが、通常より情報が少ないのは間違いないでしょう。というわけで面倒なバグ2本立てでした。失礼します。
関連記事

[2014/03/23 13:13] | 不死女 -Immortal girl-
|

モンジュライオン
モンジュラ
モンジュライオン

モンジュライオン
Shiro(管理人)
モンジュライオン。この挨拶が通じる奴を私は数えるほどしか知りませんよ。

モンジュライオン
漆黒のペスト
不死女楽しみにしております
また大須行きましょう


Shiro(管理人)
あんまり地名書かないで下さいよ(笑)


skallo
いつの間に新作が。。知らなかった


Shiro(管理人)
お久しぶりですね、Skall-Oさん。
なんと今回はヒロインフルボイス化計画が…?


skallo
PCがMacに変わったからアプリが起動しない・・
Mac OSでも起動できるようには・・(チラッ)
難しいのかな・・(チラッ)

こんばんは
Sva
おまたへ~
この前偶然にもお会いしましたね^^
『つだ』ついにウルフが登場いたしました。よろしければどうぞ覗いてやってくださいまし。

こんにちは
Sva
おまたへ~
ゲーム開発楽しみですねぇ^^頑張ってください!
『つだ』新キャラ登場いたしましたがご覧いただけたでしょうか?よろしければどうぞ~

コメント:を閉じる▲
コメント:
この記事へのコメント:
モンジュライオン
モンジュライオン
2014/04/02(Wed) 22:41 | URL  | モンジュラ #-[ 編集]
モンジュライオン
モンジュライオン。この挨拶が通じる奴を私は数えるほどしか知りませんよ。
2014/04/03(Thu) 19:45 | URL  | Shiro(管理人) #-[ 編集]
モンジュライオン
不死女楽しみにしております
また大須行きましょう
2014/04/04(Fri) 00:06 | URL  | 漆黒のペスト #-[ 編集]
あんまり地名書かないで下さいよ(笑)
2014/04/04(Fri) 20:21 | URL  | Shiro(管理人) #-[ 編集]
いつの間に新作が。。知らなかった
2014/04/18(Fri) 12:05 | URL  | skallo #-[ 編集]
お久しぶりですね、Skall-Oさん。
なんと今回はヒロインフルボイス化計画が…?
2014/04/18(Fri) 17:39 | URL  | Shiro(管理人) #-[ 編集]
PCがMacに変わったからアプリが起動しない・・
Mac OSでも起動できるようには・・(チラッ)
難しいのかな・・(チラッ)
2014/04/25(Fri) 10:09 | URL  | skallo #-[ 編集]
こんばんは
おまたへ~
この前偶然にもお会いしましたね^^
『つだ』ついにウルフが登場いたしました。よろしければどうぞ覗いてやってくださいまし。
2014/04/25(Fri) 21:26 | URL  | Sva #bWaRpPp2[ 編集]
こんにちは
おまたへ~
ゲーム開発楽しみですねぇ^^頑張ってください!
『つだ』新キャラ登場いたしましたがご覧いただけたでしょうか?よろしければどうぞ~
2014/04/27(Sun) 17:55 | URL  | Sva #bWaRpPp2[ 編集]
コメント:を投稿
URL:

パスワード:
非公開コメント: 管理者にだけ表示を許可
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。