人気ブログランキング | 話題のタグを見る

ゲームファン【ゲームサイエンス学科ブログ】

デバッグの果てに辿り着いた真相は

こんばんは、チームダイコンです。相変わらずの夜の更新となります。


前回の記事でデバッグが停滞していることについて少し触れましたが、日を跨いでやっと解決しました。
もちろん、解決に到っては先生の力をお借りしました。もし一人だったら恐らく一週間以上掛かっていたでしょうね……。
単純では有りましたが、思い入れ深いことではありますので、この場を借りて事の詳細をお伝えしようと思います。
酷い長文になります。画像ありません。動画ありません。申し訳ないです。それでも書きます。書かせて下さい。


今回直面していたのは、悪名高い、ポインタに関するエラーでした。
そして作成していたプログラムについて部分的に抜き出すと、 GameScene → ObjectManager → Player という形でポインタを保持していました。
具体的な処理順は、以下の通りです。


【ゲームスタートを押した後の処理順】

1. GameSceneのコンストラクタ開始
2. ObjectManager.cppのコンストラクタ開始
3. ObjectManager.cppのコンストラクタ終了
4. GameSceneのコンストラクタ終了
5. Gameのinitialize開始
6. ObjectManagerのinitialize開始
7. Playerのコンストラクタ開始
8. Playerのコンストラクタ終了
9. Playerのinitialize開始
10. Playerのinitialize終了
11. ObjectManagerのinitialize終了
12. Gameのinitialize終了
13. その他処理に続く……


エラーは上記の 7. あたりで起きていると推測されました。具体的には『 player_m = new Player(); 』という文です。
実際、この文のみをコメントアウトすることで、処理は問題なく続行されることも確認できました。
また、不思議なことではありますが、『 player_m = new Player(); 』を『 Player* player_2_m = new Player(); 』と置き換えても問題なく続行できました。
メンバ変数を使う代わりに、その場で宣言したメソッド内のローカル変数を使うだけであって、処理は同じはずなんですが……これは特に疑問を強めました。

その後、さらにデバッグを進め、ステップインで一文ずつ実行して行くことで、詳細に、どこの処理で止まるのかを突き止めようとしてみました。
結果、Playerのコンストラクタが完了( newが終了 )し、代入演算に入った所でエラーが起きました。

さて、これらのことから、すっかり player_m にアクセスできないのか? それはなくとも、この周辺がおかしいのか? という方向に考えが進んだことは、言うまでもありません。
ここから、泥沼に足を踏み入れていくこととなったのです。


……実際の原因はというと、至極単純なことにも、ObjectManager の initialize を呼ぶ時に使ったポインタが、初期化されていないというだけのことでした。
何故そのような当然の部分に目がいかなかったのか……言い訳にはなりますが、デバッグ時、ObjectManager の initializeは実行されていたのです。
いえ、正常に実行されていたかは分かりませんが、前述した通り、ObjectManager の initialize 開始後から少し進んだところ、Playerのコンストラクタ終了直後にプログラムは止まったのです。
この時点で、もし 前述のObjectManager*型ポインタが初期化されていなければ、initialize 開始時点で止まるだろうと思い込んでしまっていたので、そこに目を向けることをしなかったのです。
もっと言うと、ポインタが初期化されているかどうかなどの確認方法をよく分かっていなかったということもありました。
先生が普通にやっているのを傍から見て、そんなことできるのか! と、一人でデバッガを胸中で称賛していました。


結局、ソースコードとエラー情報を見せたところで、先生が素早くポインタに目をつけ、中身をチェックして下さったので、初期化されていないことが分かり、問題は解決しました。

初期化してないかどうかくらい、ざざっと見ても分かるだろう、ということですが、実は初期化しているつもりになっている文が以下のようになっていまして。

『 objectManager_m->ObjectManager::getInstance(); 』

まあ、なんというか、物凄い奇特な文になっていたわけですが、逆に気づきませんでした。本来の文はこうです。

『 objectManager_m = ObjectManager::getInstance(); 』

シングルトンにはありがちな形です。
間違っている方の文が、文法チェックで検出されないことにはびっくりしましたが……よくよく見れば文の意味は通っているんですよね。凄まじくまどろっこしいというか、冗長、奇々怪々な文ではありますが。


あまりにもありがちなミスであっただけに、先生に指摘された際には力が抜けましたが、いろいろな要素が複合した結果、ミスリードされてしまった、という経緯があるので、自分的には仕方がなかったかも知れないと、合理化している部分があります。

とりあえず、『 まずは全ての変数の中身、特にポインタに注意してひと通り確認することが大切』 を結論、教訓、戒めとして、この話を締めくくろうと思います。
お疲れ様でした。



トライデントコンピュータ専門学校 ゲームサイエンス学科についてはコチラ!

by trident-game | 2013-06-03 23:01

専門学校トライデント ゲームサイエンス学科のブログ
by trident-game

ゲームプログラミング体験入学

最新のトラックバック

ライフログ

検索

ブログパーツ

ファン

記事ランキング

ブログジャンル

画像一覧