ページ 11

Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 08:52
by かなたん
MFC ウィンドウを閉じてもプロセスに残ってしまう。
をきっかけに、今作っているマインスイーパーをDoc-Viewアーキテクチャにのっとって書き換えようとしています。
(書き換える前の状況はバックアップ済みです。)
Doc-Viewアーキテクチャって、Viewは描画関係の記述中心で、その他データ処理などはDocに記述するってことですよね?
元のソースは上記トピックにあるのでここでは提示しないことにしますが、マインスイーパーではだいたい以下のような感じでしょうか?
ViewはOnDrawでの描画処理と各種イベントハンドラー、その他必要な関数の呼び出しと再描画命令の記述する。
Docはマスの状況などを記憶させ、マスが押された時にマスの状況がどう変化するのか、ゲーム終了時の外部ファイルへの記録の書き出しなどを記述する。
Set/KillTimerもOnTimerがViewにあることからViewに記述しますよね?
なんて考えて今のところ以下のように分けてみました。
(長くなるのでスポイラーで表示しています。)
マインスイーパーView.cpp
► スポイラーを表示
マインスイーパーDoc.cpp
► スポイラーを表示
ですが、実行してみてもウィンドウが立ちあがらないときがあります。
それも、たまにではなくほとんどです。
デバッグしてみると「マインスイーパー.exe の 0x00ad49f5 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xfdfdfe11 を読み込み中にアクセス違反が発生しました。」と言われ、マインスイーパーDoc.cppの135行目に矢印がありました。
自動変数にあるmap[x2]を見てみると、「CXX0030: エラーです: 式を評価できません」とあり、どうやらmallocに失敗しているみたいなのですが、何が原因なのでしょうか?
(mapはint**型で宣言していて、mallocで9*9(私が作るマインスイーパーのデフォルトで作った場合)の2次元配列にしています。)
Viewで書いていた時にはこのようなことは一度もありませんでした。
また、そもそもこのような書き方であっていると言えるのでしょうか?

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 12:17
by softya(ソフト屋)
たぶん、Viewが先に生成されるのでマズイんじゃないかと思うわけです。
ViewのOnInitialUpdateでタイマーを設定してみては?

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 12:27
by かなたん
softya(ソフト屋) さんが書きました:たぶん、Viewが先に生成されるのでマズイんじゃないかと思うわけです。
ViewのOnInitialUpdateでタイマーを設定してみては?
画面内をクリックしたらタイマー作動にしているので、ViewのOnLButtonDownなどでSetTimer(1,1000,NULL);をしているのですが、そういう書き方はよくなかったということでしょうか?

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 12:31
by softya(ソフト屋)
さすがにクリックまでにはDocも初期化されていると思うのですが、どこか順番が行き違うタイミングが有るんだと思います。それを調べ出さないとマズイです。特にリリースビルドすると問題は顕著になるでしょう。

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 12:46
by Ryo

コード:

   if((x2>-1 && x<blocks.x) && (y2>-1 && y<blocks.y) 
ここ、xとblocks.x比較してるけど、x2はx+1まで行くからダメでは?

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 18:06
by かなたん

コード:

if((x2>-1 && x2<blocks.x) && (y2>-1 && y2<blocks.y) && map[x2][y2]!=9){
	map[x2][y2]++;
}
であるとき、x=0or8でx2=-1or9となっても(y,y2も同様)mapの比較をする前でfalseになって、そのあとの比較をやめるのではないのですか?
私は少なくともMFCではその考えてやっていますし、Docを使わずにViewのみでやっていたときでも爆弾が端(x or y=0or8)にあってもエラーにはなったことはありません。
って、そういう話ではなかったでしょうか?
あ。
mallocに失敗しているように見えたのは、そうやってx2やy2がmapの範囲外にいるからですね。
ということは、問題はmapではないかもと・・・

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 18:31
by かなたん

コード:

if((x2>-1 && x<blocks.x) && (y2>-1 && y<blocks.y) && map[x2][y2]!=9){
という問題の条件文についてもう少し調べてみました。
すると、x,y,x2,y2についてウォッチ式で「CXX0017: エラーです: シンボル "x" が見つかりません」というように言われました。
とりあえず原因はmapではなさそうです。
でも、なぜこのように言われるのでしょうか?
x,yはその前にfor文で使ったりしていましたが、そのx,yはfor文内で定義したものですし、それはそのforの中だけのはずですよね?
そのあと別にきちんと定義していますし、あの条件文よりも前のwhileなどで使っていてもエラーが起こらないので、なぜあのように言われるのか・・・
x2,y2はその直前のforで初めて定義して使ったものですし・・・

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 19:09
by softya(ソフト屋)
リリースビルドしていたらエラーになるかも知れませんね。

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 20:39
by かなたん
softya(ソフト屋) さんが書きました:リリースビルドしていたらエラーになるかも知れませんね。
Releaseでビルドしてみても、ビルドエラーにはなりませんでした。
そのままでバックしてみても、状況は変わりませんでした。

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 20:51
by softya(ソフト屋)
そのエラー「CXX0017: エラーです: シンボル "x" が見つかりません」が出るのはforでのブロックの中なんですよね?
デバッグビルドでも生存ブロックの外だとそうなると思います。

Re: Doc-Viewアーキテクチャの書き方について質問です。

Posted: 2013年4月12日(金) 22:42
by かなたん
はっきりどの値でエラーになるのかを調べるべく途中結果を出力するようにし、バックアップを取っていたうまくいく方でも同じようにしようと思ったときに、うまくいく方でもエラーが出るようなりました。
なぜだろうと元に戻し比較してみたら原因がわかりました。

コード:

//分ける前のソースにあった条件文
if((x2>-1 && x2<blocks.x) && (y2>-1 && y2<blocks.y) && map[x2][y2]!=9){
//すべてx2,y2になっていた

//分けた後のソースにあった条件文
if((x2>-1 && x<blocks.x) && (y2>-1 && y<blocks.y) && map[x2][y2]!=9){
//blocksの比較の部分は2が付いていなかった
分けているほうでもすべてx2,y2にしたところ、何度新規ゲームを選んでみてもエラーが出なくなりました。
消したつもりはなかったのですが、コピペしたりしているうちにうっかり消してしまっていたのかもしれません。
すいませんでした。
ありがとうございました。