ページ 1 / 1
変数の値が変になる
Posted: 2012年7月11日(水) 16:12
by LisetteLander
int型変数UnitCharacterNum(キャラクター数)とGunNum(武器の数)を設定し、
スペースキーが押されたらRound管理クラスのコンストラクタにそれらを渡して
Round管理クラスがキャラクターと武器を保持しFreeGame関数に移る
という内容なのですが、
スペースキーを押すと動作が停止しました~というエラーが出ます。
ブレークポイントでそれぞれの変数の値を見たところ
7行目で0,0
9行目で851981,19
という数値になります。(何回やっても数値は同じでした)
どうすれば解決するでしょうか?
コード:
void Administrator::FreeGameIni(){
const int SelectPropertiesNum=2;
int* SelectProperties[SelectPropertiesNum]={&UnitCharacterNum,&GunNum};
DrawFormatString(10,10,256000,"スペースキーでスタートESCで戻る");
DrawFormatString(10,30,256000,"人数");
DrawFormatString(100,30,256000,"%d",UnitCharacterNum);
DrawFormatString(10,60,256000,"銃の数");
DrawFormatString(100,60,256000,"%d",GunNum);
if(1==DeviceInput.InputKey(KEY_INPUT_UP)){
Select+=SelectPropertiesNum-1;
}
if(1==DeviceInput.InputKey(KEY_INPUT_DOWN)){
Select++;
}
if(1==DeviceInput.InputKey(KEY_INPUT_RIGHT)){
*SelectProperties[Select]+=1;
}
if(1==DeviceInput.InputKey(KEY_INPUT_LEFT)){
*SelectProperties[Select]-=1;
}
Select%=SelectPropertiesNum;
//Round作成
if(1==DeviceInput.InputKey(KEY_INPUT_SPACE)){
Round = new CRound(UnitCharacterNum,GunNum);
SetState(&Administrator::FreeGame);
}
if(1==DeviceInput.InputKey(KEY_INPUT_ESCAPE)){
SetState(&Administrator::TitleMenu);
}
}
Re: 変数の値が変になる
Posted: 2012年7月11日(水) 17:52
by softya(ソフト屋)
分からないことや気になった点です。
(1) 何処の何かわかりません。
7行目で0,0
9行目で851981,19
と書かれているのはソースコードの行番号と対応しないのですが、どういう操作をしてなんの数値のことでしょうか?
(2)Selectの初期値が不明です。
(3)19行目のSelect++;はSelect--;では?
(4)29行目のSelect%=SelectPropertiesNum;の前の23行と26行目の処理が配列範囲外になる恐れがあります。
(5)32行目の処理でストッパがないので押している間、Round = new CRound(UnitCharacterNum,GunNum);が繰り返されます。
メモリリークが起こると思います。
Re: 変数の値が変になる
Posted: 2012年7月11日(水) 18:46
by LisetteLander
softya(ソフト屋) さんが書きました:(1) 何処の何かわかりません。
ブレークポイントを一行目に設置しステップインしていった結果、
7行目時の変数の値と9行目時の変数の値です。
それでもDrawFormatString()は関係ないと思いますけど・・・

- 無題.png (31.79 KiB) 閲覧数: 4706 回
softya(ソフト屋) さんが書きました:(2)Selectの初期値が不明です。
失礼しました。
コンストラクタの初期化リストで0を指定しています。
softya(ソフト屋) さんが書きました:(3)19行目のSelect++;はSelect--;では?
(4)29行目のSelect%=SelectPropertiesNum;の前の23行と26行目の処理が配列範囲外になる恐れがあります。
http://dixq.net/g/03_04.html
此方の処理を真似させていただいき、正常に動いているように見えたので大丈夫かと思っていたのですが、
ダメだったでしょうか?
softya(ソフト屋) さんが書きました:(5)32行目の処理でストッパがないので押している間、Round = new CRound(UnitCharacterNum,GunNum);が繰り返されます。
メモリリークが起こると思います。
説明不足で申し訳ありません。
SetState(&Administrator::FreeGame);
は関数ポインタ Administrator.Func の値を FreeGame() のアドレスに設定する関数です。
コンストラクタでの初期化リストでFunc(&Administrator::FreeGameIni)を指定しています。
Re: 変数の値が変になる
Posted: 2012年7月11日(水) 19:04
by softya(ソフト屋)
(1)
>ブレークポイントを一行目に設置しステップインしていった結果、
>7行目時の変数の値と9行目時の変数の値です。
>それでもDrawFormatString()は関係ないと思いますけど・・・
UnitCharacterNumとGunNumの初期値はどうなっているんでしょうか?
(3)に関しては上下を間違えました。失礼しました。
(4)に関しては順番的にマズイと思うので、SelectProperties[0]とSelectProperties[1]以外を2回連続のKEY_INPUT_DOWN時にselect変数が指すと思います。デバッガで確認してみて下さい。
(5)に関してはSetStateで関数が切り替わり呼ばれなく成るって事でしょうか?
それでも、Administrator::FreeGameIniが再度設定される可能性があるのならマズイと思いますが。
Re: 変数の値が変になる
Posted: 2012年7月11日(水) 20:43
by LisetteLander
(1)
両方とも0です。
(4)
確かに、スペースキーと矢印キーを同時に押されたら領域外アクセスになりますね。
UP,DOWNとRIGHT,LEFTの分岐の間に
Select%=SelectPropertiesNum;
を移動して修正しました。
(5)
Administrator.RoundというRound変数があり、
FreeGameIniでインスタンス化
FreeGameで使用して
FreeGameFinでDeleteしてTitleMenuに戻るので、恐らく・・・大丈夫だと思います。
FreeGameはFreeGameIniからのみ遷移し、FreeGameFinにしか遷移できません。
FinからはTitleMenuにしか遷移できません。
StoryGameIniという同様の関数があってもTitleMenuからしか遷移できません。
Re: 変数の値が変になる
Posted: 2012年7月11日(水) 21:23
by softya(ソフト屋)
Administratorクラスの宣言部分を確認したいのと、関数アドレスの設定方法からするとAdministrator::FreeGameIni等はstaticなメンバ関数だと思うのですが、Administratorクラスのインスタンスを作るタイミングとAdministrator::FreeGameIniが呼び出されるタイミングは大丈夫なのでしょうか? UnitCharacterNumやGunNumやSelectの初期値などコンストラクタが正しく呼び出されているか不安になりました。
【補足】
もしコンストラクタでなくてもUnitCharacterNumとGunNumの宣言の仕方や初期化についても教えて下さい。
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 10:33
by LisetteLander
ずらずらっと書き並べさせて頂きます。
コンストラクタで指定されているのはFreeGameIniではなくTitleMenuでした。
すいません。
静的関数については
http://marupeke296.com/GDEV_No7_StateImpliment2.html
こちらのデザインの⑤あたりを真似させて頂きました。
正直「?」な所がありますが・・・
main.cpp
コード:
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE),SetGraphMode(X_WINDOW,Y_WINDOW,16),DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
Administrator* Admin = new Administrator();
while(ProcessLoop()==0){
if(!Admin->Refresh())break;
}
delete Admin;
DxLib_End(); // DXライブラリ終了処理
return 0;
}
宣言部
コード:
class Administrator{
private:
CDeviceInput DeviceInput;
CRoundScene* RoundScene;
//
//選択中のユニットキャラクター数
int UnitCharacterNum;
int GunNum;
int Select;
void TitleMenu();
void FreeGameIni();
void FreeGame();
void End();
//メソッドを指定します
void SetState(void( Administrator::*func )());
//Trueの場合このクラスはRefreshメソッドにより終了します
bool IsEnd;
//指定中のメソッドのアドレスを格納します
void (Administrator::*Func)(); //関数ポインタ
public:
Administrator();
~Administrator();
//指定中のメソッドを実行します
bool Refresh();
};
定義
コード:
void Administrator::TitleMenu(){
DrawFormatString(10,10,256000,"スペースキーでフリー\nエスケープキーで終了");
if(1==DeviceInput.InputKey(KEY_INPUT_SPACE)){
SetState(&Administrator::FreeGameIni);
}
if(1==DeviceInput.InputKey(KEY_INPUT_ESCAPE)){
SetState(&CGameAdministrator::End);
}
}
void Administrator::FreeGameIni(){
const int SelectPropertiesNum=2;
int* SelectProperties[SelectPropertiesNum]={&UnitCharacterNum,&GunNum};
DrawFormatString(10,10,256000,"スペースキーでスタートESCで戻る");
DrawFormatString(10,30,256000,"人数");
DrawFormatString(100,30,256000,"%d",UnitCharacterNum);
DrawFormatString(10,60,256000,"銃の数");
DrawFormatString(100,60,256000,"%d",GunNum);
if(1==DeviceInput.InputKey(KEY_INPUT_UP)){
Select+=SelectPropertiesNum-1;
}
if(1==DeviceInput.InputKey(KEY_INPUT_DOWN)){
Select++;
}
Select%=SelectPropertiesNum;
if(1==DeviceInput.InputKey(KEY_INPUT_RIGHT)){
*SelectProperties[Select]+=1;
}
if(1==DeviceInput.InputKey(KEY_INPUT_LEFT)){
*SelectProperties[Select]-=1;
}
//Round作成
if(1==DeviceInput.InputKey(KEY_INPUT_SPACE)){
RoundScene = new CRoundScene(UnitCharacterNum,GunNum);
SetState(&Administrator::FreeGame);
}
if(1==DeviceInput.InputKey(KEY_INPUT_ESCAPE)){
SetState(&Administrator::TitleMenu);
}
}
void Administrator::FreeGame(){
//きっとヌルポにはならない
if(FINISH==RoundScene->Refresh()){
delete RoundScene;
SetState(&Administrator::TitleMenu);
}
}
void Administrator::End(){
IsEnd=FINISH;
}
Administrator::Administrator():IsEnd(CONTINUE),Func(&Administrator::TitleMenu),UnitCharacterNum(0),GunNum(0),Select(0){}
Administrator::~Administrator(){}
void Administrator::SetState(void( Administrator::*func )()){
Func = func;
}
bool Administrator::Refresh(){
// メソッドポインタを実行
(this->*Func)();
//このクラスが終了するかどうか
//終了しない場合次のメソッドに移ります。
return IsEnd;
}
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 10:40
by LisetteLander
CRoundSceneのコンストラクタも・・
コード:
CRoundScene::CRoundScene(int tmpUnitCharacterNum,int tmpGunNum):IsEnd(CONTINUE),Func(&CRoundScene::Load),UnitCharacterNum(tmpUnitCharacterNum),GunNum(tmpGunNum){
//Gun配列設定
Gun = new CGun[GunNum];
for(int i=0;i<tmpGunNum;i++){
// Gun[i].AllSet();
}
//Character配列設定
UnitCharacter=new CUnitCharacter[UnitCharacterNum];
for(int i=0;i<tmpUnitCharacterNum;i++){
// UnitCharacter[i].AllSet();
}
}
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 11:38
by softya(ソフト屋)
見せた頂いたコードでは特に問題は無いと思います。
ただ、CRoundSceneのコンストラクタで数値の上限下限チェックを行ったほうが良いと思います。
※ tmpUnitCharacterNum,tmpGunNumの事です。
それでも問題が残るなら全体のコードを見せて頂かないと再現性がないので難しいです。
投稿時のファイル添付機能でプログラム全体をzip圧縮して添付して下さい。
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 19:56
by LisetteLander
あれ?
失礼しました。
CRoundSceneのコンストラクタの内容を直して返信させてもらったのですが、
その時に治った?ようです。
下が本来のコードでした。
紛らわしいことをしてしまい申し訳ないです。
コード:
CRoundScene::CRoundScene(int tmpUnitCharacterNum,int tmpGunNum):IsEnd(CONTINUE),Func(&CRoundScene::Load),UnitCharacterNum(tmpUnitCharacterNum),GunNum(tmpGunNum){
//Gun配列設定
for(int i=0;i<GunNum;i++){
new(&Gun+i) CGun(/*テスト*/);
}
//Character配列設定
for(int i=0;i<UnitCharacterNum;i++){
new(&UnitCharacter+i) CUnitCharacter(/*テスト*/);
}
}
記述がめちゃくちゃだったのでしょうか?
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 21:07
by softya(ソフト屋)
CGunやCUnitCharacterのクラス定義が分かりませんので何とも答えられません。
operator newのオーバーロード次第って感じです。
Re: 変数の値が変になる
Posted: 2012年7月12日(木) 21:11
by LisetteLander
なんだかよくわからないですが、No.8に変更したことでバグが治ったということで解決とさせて頂きます。
コンストラクタだけで全部賄おうとしたのが間違いだったんですね・・・