変数の値が変になる

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

変数の値が変になる

#1

投稿記事 by LisetteLander » 13年前

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);
	}
}
最後に編集したユーザー LisetteLander on 2012年7月11日(水) 20:39 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 変数の値が変になる

#2

投稿記事 by softya(ソフト屋) » 13年前

分からないことや気になった点です。

(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);が繰り返されます。
メモリリークが起こると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#3

投稿記事 by LisetteLander » 13年前

softya(ソフト屋) さんが書きました:(1) 何処の何かわかりません。
ブレークポイントを一行目に設置しステップインしていった結果、
7行目時の変数の値と9行目時の変数の値です。
それでもDrawFormatString()は関係ないと思いますけど・・・
無題.png
無題.png (31.79 KiB) 閲覧数: 4711 回
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)を指定しています。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 変数の値が変になる

#4

投稿記事 by softya(ソフト屋) » 13年前

(1)
>ブレークポイントを一行目に設置しステップインしていった結果、
>7行目時の変数の値と9行目時の変数の値です。
>それでもDrawFormatString()は関係ないと思いますけど・・・

UnitCharacterNumとGunNumの初期値はどうなっているんでしょうか?

(3)に関しては上下を間違えました。失礼しました。
(4)に関しては順番的にマズイと思うので、SelectProperties[0]とSelectProperties[1]以外を2回連続のKEY_INPUT_DOWN時にselect変数が指すと思います。デバッガで確認してみて下さい。
(5)に関してはSetStateで関数が切り替わり呼ばれなく成るって事でしょうか?
それでも、Administrator::FreeGameIniが再度設定される可能性があるのならマズイと思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#5

投稿記事 by LisetteLander » 13年前

(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からしか遷移できません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 変数の値が変になる

#6

投稿記事 by softya(ソフト屋) » 13年前

Administratorクラスの宣言部分を確認したいのと、関数アドレスの設定方法からするとAdministrator::FreeGameIni等はstaticなメンバ関数だと思うのですが、Administratorクラスのインスタンスを作るタイミングとAdministrator::FreeGameIniが呼び出されるタイミングは大丈夫なのでしょうか? UnitCharacterNumやGunNumやSelectの初期値などコンストラクタが正しく呼び出されているか不安になりました。

【補足】
もしコンストラクタでなくてもUnitCharacterNumとGunNumの宣言の仕方や初期化についても教えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#7

投稿記事 by LisetteLander » 13年前

ずらずらっと書き並べさせて頂きます。
コンストラクタで指定されているのは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;
}

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#8

投稿記事 by LisetteLander » 13年前

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();
	}
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 変数の値が変になる

#9

投稿記事 by softya(ソフト屋) » 13年前

見せた頂いたコードでは特に問題は無いと思います。
ただ、CRoundSceneのコンストラクタで数値の上限下限チェックを行ったほうが良いと思います。
※ tmpUnitCharacterNum,tmpGunNumの事です。

それでも問題が残るなら全体のコードを見せて頂かないと再現性がないので難しいです。
投稿時のファイル添付機能でプログラム全体をzip圧縮して添付して下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#10

投稿記事 by LisetteLander » 13年前

あれ?
失礼しました。

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(/*テスト*/);
	}
}
記述がめちゃくちゃだったのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 変数の値が変になる

#11

投稿記事 by softya(ソフト屋) » 13年前

CGunやCUnitCharacterのクラス定義が分かりませんので何とも答えられません。
operator newのオーバーロード次第って感じです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
LisetteLander
記事: 147
登録日時: 14年前
住所: 東京

Re: 変数の値が変になる

#12

投稿記事 by LisetteLander » 13年前

なんだかよくわからないですが、No.8に変更したことでバグが治ったということで解決とさせて頂きます。

コンストラクタだけで全部賄おうとしたのが間違いだったんですね・・・

閉鎖

“C言語何でも質問掲示板” へ戻る