龍神録+タイトルセレクト

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
山中

龍神録+タイトルセレクト

#1

投稿記事 by 山中 » 13年前

こんばんは。昨日質問させていただいたものです。

連日ですみませんが、質問したいことがあります。

環境はWin7、VC++2008EEです。
C言語初心者です。
僕は龍神録のコードを参考に勉強させていただいているのですが、プログラミングの館のタイトルセレクトを加えてみようと思い、実装しようとコードを書いたのですが、実行はされるものの十数秒経つと終了し、
「実験.exe の 0x00f496ae でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 に書き込み中にアクセス違反が発生しました。」と表示され、また呼び出し履歴には 「[下のフレームは間違っているか、または見つかりません。kernel32.dll に対して読み込まれたシンボルはありません。] 」と表示されてしまいます。

タイトルセレクトを行う関数を加えようとしてこうなったため、その関数が原因だとおもうのですが、ここ何日か、デバッガを使って配列や変数をしらべても、原因がどうしてもわかりません。

判断に必要だと思うコードを貼りますので、ご指摘をお願いしたいのです。

main.cpp

コード:


#define GLOBAL_INSTANCE
#include "GV.h"




//ループで必ず行う3大処理
int ProcessLoop(){
		if(ProcessMessage()!=0) return -1;
		if(ClearDrawScreen()!=0) return -1;
		GetHitKeyStateAll_2();
		GetHitPadStateAll();
		return 0;
}

//タイトルセレクト
void TitleSelect(){
		Menumozi_t Menumozi[5]={
				{80,100,"ゲームスタート"},
				{100,150,"おまけ"},
				{100,200,"サウンド"},
				{100,250,"コンフィグ"},
				{100,300,"ゲーム終了"},
		};
	    static int SelectNum;

		

		if(CheckStateKey(KEY_INPUT_DOWN)==1){
				SelectNum = (SelectNum+1)%5;
		

		for(int i=0;i<5;i++){
				if(i==SelectNum){
						Menumozi[i].x = 80;
				}
				else{
						Menumozi[i].x = 100;
				}
		}
		}
		for(int i=0;i<5;i++){
				DrawFormatString(Menumozi[i].x,Menumozi[i].y,GetColor(255,255,255),Menumozi[i].name);
		}
		printfDx("%d",SelectNum);
		if(SelectNum==0 && CheckStateKey(KEY_INPUT_Z)>0){
		func_state=99;
		}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
		ChangeWindowMode(TRUE);
		DxLib_Init();
		SetDrawScreen(DX_SCREEN_BACK);

		
		
		while(ProcessLoop()==0 ){
				if(CheckStateKey(KEY_INPUT_ESCAPE)==60)break;

				music_ini();
				
				switch(func_state){
						case 0:
								load();
								first_ini();
								DrawGameTitle();
								TitleSelect();
								
                                break;
                        case 99://STGを始める前に行う初期化
                                 ini();
								 load_story();

                                 func_state=100;
                                 break;
						case 100:
								calc_ch();
                                ch_move();      //キャラクタの移動制御
								cshot_main();
                                enemy_main();
								shot_main();//ショットメイン
								boss_shot_main();
								out_main();
								effect_main();//エフェクトメイン
								graph_main();
								if(boss.flag==0)
										stage_count++;
								break;
						default:
								printfDx("不明なfunc_state\n");
								break;
				}
				music_play();


	
				

				ScreenFlip();
				count++;
		}


		DxLib_End();

		return 0;
}
struct.hの構造体定義

コード:

//タイトルの構造体
typedef struct{
		int x,y;
		char name[128];//項目文字用変数
}Menumozi_t;


ご協力をお願いします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 龍神録+タイトルセレクト

#2

投稿記事 by h2so5 » 13年前

インデントが汚いですが、コードにおかしなところは見当たらないので別のところではないかと思います。
デバッガを使っているなら呼び出し履歴から問題の箇所を判断できませんか?

山中

Re: 龍神録+タイトルセレクト

#3

投稿記事 by 山中 » 13年前

呼び出し履歴で判断できる問題の箇所は「kernel32.dll に対して読み込まれたシンボルはありません。」だと思うのですが、見慣れないもので、対策が思いつきません。これはどういった意味なのでしょう。

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

Re: 龍神録+タイトルセレクト

#4

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

「kernel32.dll に対して読み込まれたシンボルはありません。」は出力ウィンドウで呼び出し履歴ウィンドウではないのでは?

「実験.exe の 0x00f496ae でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 に書き込み中にアクセス違反が発生しました。」が出た時にちゃんと中断してますか?
デバッグ開始で開始すれば中断できるはずですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#5

投稿記事 by 山中 » 13年前

確認する限りでは、呼び出し履歴の中の指摘です。

中断もしております。

ただ、中断した際に、66行目のfirst_ini()のところに緑の矢印があって「このスレッドによって現在の関数が実行された後、次に実行されるステートメントです」と記されているのが確認できます。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 龍神録+タイトルセレクト

#6

投稿記事 by h2so5 » 13年前

タイトル画面を表示している間、load() と first_ini() が毎フレーム呼ばれるようですが、
関数の名前からすると最初に一度だけ実行するような関数ではないのでしょうか?

実際に、case 99の場合はini() と load_story(); は1度だけ呼ばれるようになっています。

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

Re: 龍神録+タイトルセレクト

#7

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

文字通り呼び出し履歴なので呼び出しを逆にだどれるはずですが、自分の関数から他のライブラリ関数に移るときの関数の名前と命令は何でしょうか?
そして、そこの部分のソースコードを見せて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#8

投稿記事 by 山中 » 13年前

申し訳ありません。聞かれたことが私にはまだ難しく、うまく回答することができません。
お手間をかけさせてしまいますが、
まず呼び出し履歴の一番下に[下のフレームは間違っているか、または見つかりません。kernel32.dll に対して読み込まれたシンボルはありません。]というメッセージがあり、
その上に kernel32.dll!75a433aa() とあります。
そしてその上に呼び出し元(?)の実験.exe!WinMain(HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000) 行 66
とあります。さらにその上に実験.exe!DxLib::LoadSoundMemBase() + 0x119 バイト というメッセージがあります。見るべきところはここで合っていますでしょうか。

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

Re: 龍神録+タイトルセレクト

#9

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

それだと、実験.exe!WinMain(HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000) 行 66をダブル・クリックすると、どこの命令が表示されますか? そこを含めた関数のソースコードを教えて下さい。

あれ? これがload()ですかね? だとするとLoadSoundMemBaseとの間に幾つか関数が経由されるはずなのですが。

[補足説明]
呼び出しは、大雑把にはこのような関係になっています。

OS → kernel32 → WinMain → 何かの関数 → LoadSoundMemBase()
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#10

投稿記事 by 山中 » 13年前

ご指摘されたところをダブルクリックしたところ、66行目のfirst_ini()を指されます。

またそのコードは

コード:

//一番最初の初期化
void first_ini(){
	    configpad.down=0;
		configpad.left=1;
		configpad.right=2;
		configpad.up=3;
		configpad.bom=5;
		configpad.shot=4;
		configpad.slow=6;
		configpad.start=13;
		configpad.change=6;
		//例:弾0は76x76ピクセルで、5色あり、当たり範囲17ピクセル
        input_bullet_info(&bullet_info[0],76, 76, 5,17.0);
        input_bullet_info(&bullet_info[1],22, 22, 6, 4.0);
        input_bullet_info(&bullet_info[2], 5,120,10, 2.5);
        input_bullet_info(&bullet_info[3],19, 34, 5, 2.0);
        input_bullet_info(&bullet_info[4],38, 38,10, 2.0);
        input_bullet_info(&bullet_info[5],14, 16, 3, 3.5);
        input_bullet_info(&bullet_info[6],14, 18, 3, 2.0);
        input_bullet_info(&bullet_info[7],16, 16, 9, 2.5);
        input_bullet_info(&bullet_info[8],12, 18,10, 1.5);
        input_bullet_info(&bullet_info[9],13, 19, 3, 2.0);

}
となります。


またh2so5さんのご返信に、レスが埋もれていて気づけませんでした。
たしかに、おっしゃるとおりだと思います。
最初に書いたとおり、タイトル関連の関数(DrawGameTitle();とTitleSelect();)は、龍神録とは別に、私が勝手に加えたものです。
一度だけしか行われないはずの関数と同じ場所にタイトル関連の関数をおいてしまっていることが原因なのでしょうか・・・

山中

Re: 龍神録+タイトルセレクト

#11

投稿記事 by 山中 » 13年前

連レスすみません。私のプログラム画面だと66行目はfirst_ini()なのですが、なぜかこちらだとload()のようです。まぎらわしくてすみません

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

Re: 龍神録+タイトルセレクト

#12

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

どこの命令ですか? あとその先の関数は辿れないでしょうか?
input_bullet_infoに行っているはずですが。bullet_infoの配列の宣言も気になります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#13

投稿記事 by 山中 » 13年前

さっきから時間をとらせてすみません、どこの命令かというのは、答え方がよくわからないのですが、実験.exe!WinMain(HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000) 行 66をダブルクリックするとfirst_ini()が指されます。
また、実験.exe!WinMain(HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000, HINSTANCE__ * __formal=0x7efde000) 行 66の実験.exe!DxLib::LoadSoundMemBase() + 0x119 バイト なのですが、それ以上上の関数をダブルクリックしても「現在の場所のソース コードを表示できません。」と表示されてたどることができません・・。

またbullet_infoの宣言、定義です。

コード:



//弾の情報
typedef struct{
		int size_x,size_y,col_num;
		double range;
}bullet_info_t;

コード:

//渡された情報を構造体に入れる関数
void input_bullet_info(bullet_info_t *binfo,int size_x,int size_y,int col_num,double range){
        binfo->size_x =size_x;  binfo->size_y =size_y;
        binfo->col_num=col_num; binfo->range  =range;
}

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

Re: 龍神録+タイトルセレクト

#14

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

すいません。大きな疑問ですがリリースビルドではありませんか?
デバッグビルドで実行していないとマトモに呼び出し履歴は利用できません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#15

投稿記事 by 山中 » 13年前

そこは大丈夫です。
デバッグビルドです。

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

Re: 龍神録+タイトルセレクト

#16

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

山中 さんが書きました:そこは大丈夫です。
デバッグビルドです。
first_ini()→LoadSoundMemBase()のはずはないので間が飛ばされています。
first_ini()→何かの関数→LoadSoundMem()って流れはあるんでしょうか?

bullet_infoの配列の要素数のほうが知りたいです。10個位上ありますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#17

投稿記事 by 山中 » 13年前

呼び出し履歴をみても、WinMainの次はLoadSoundMemBase()としか確認できないです・・・。
呼び出し履歴に記されている関数はWinMain、 LoadSoundMemBase() 、 LoadBmpToGraph() 、 CreateGraphImage_plus_Alpha() 、 CreateGraphImageOrDIBGraph() 、CreateGraphImageType2() 、
LoadPngImage() 、MEMCPY() という僕には見慣れない関数ばかりです。

コード:


GLOBAL bullet_info_t bullet_info[10];//10個の弾情報

十個あります

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

Re: 龍神録+タイトルセレクト

#18

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

自分でやっているはずのサウンドのロード関数を呼び出すまでの流れを教えて下さい。
たぶん、呼び出し履歴の情報がプログラムによって破壊されています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#19

投稿記事 by 山中 » 13年前

あの、h2so5さんの指摘が気になって

コード:

#define GLOBAL_INSTANCE
#include "GV.h"




//ループで必ず行う3大処理
int ProcessLoop(){
		if(ProcessMessage()!=0) return -1;
		if(ClearDrawScreen()!=0) return -1;
		GetHitKeyStateAll_2();
		GetHitPadStateAll();
		return 0;
}

//タイトルセレクト
void TitleSelect(){
		Menumozi_t Menumozi[5]={
				{80,100,"ゲームスタート"},
				{100,150,"おまけ"},
				{100,200,"サウンド"},
				{100,250,"コンフィグ"},
				{100,300,"ゲーム終了"},
		};
	    static int SelectNum;

		

		if(CheckStateKey(KEY_INPUT_DOWN)==1){
				SelectNum = (SelectNum+1)%5;
		

		for(int i=0;i<5;i++){
				if(i==SelectNum){
						Menumozi[i].x = 80;
				}
				else{
						Menumozi[i].x = 100;
				}
		}
		}
		for(int i=0;i<5;i++){
				DrawFormatString(Menumozi[i].x,Menumozi[i].y,GetColor(255,255,255),Menumozi[i].name);
		}
		printfDx("%d",SelectNum);
		if(SelectNum==0 && CheckStateKey(KEY_INPUT_Z)>0){
		func_state=99;
		}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
		ChangeWindowMode(TRUE);
		DxLib_Init();
		SetDrawScreen(DX_SCREEN_BACK);

		
		
		while(ProcessLoop()==0 ){
				if(CheckStateKey(KEY_INPUT_ESCAPE)==60)break;

				music_ini();
				
				switch(func_state){
						case 0:
								load();
								first_ini();
								func_state=98;
							
								
                                break;

						case 98://タイトル関係
								 DrawGameTitle();
								 TitleSelect();
									
								 break;


                        case 99://STGを始める前に行う初期化
                                 ini();
								 load_story();

                                 func_state=100;
                                 break;
						case 100:
								calc_ch();
                                ch_move();      //キャラクタの移動制御
								cshot_main();
                                enemy_main();
								shot_main();//ショットメイン
								boss_shot_main();
								out_main();
								effect_main();//エフェクトメイン
								graph_main();
								if(boss.flag==0)
										stage_count++;
								break;
						default:
								printfDx("不明なfunc_state\n");
								break;
				}
				music_play();


	
				

				ScreenFlip();
				count++;
		}


		DxLib_End();

		return 0;
}
という風に、switchのケースを一つ増やしたら途中でエラーが起きることがなくなりました・・・(行間やインデントは直していきます・・・)
やはり、一度だけ行わせる関数をタイトル関連の関数のせいで何度も行わせていた(?)のが問題だったのでしょうか。。。

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

Re: 龍神録+タイトルセレクト

#20

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

その可能性が高いですね。
ただ、メモリ上の情報を破壊するバグは気になりますけどね。
何かの拍子に再発しないと良いのですが・・・。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

山中

Re: 龍神録+タイトルセレクト

#21

投稿記事 by 山中 » 13年前

再発の恐れがあるバグの対策に関しては、まだまだ自分は勉強不足です・・・。
今後とも勉強をつづけ、もし再発するようなことがあれば、自分で解決する努力をしますが、またこちらでお世話になるかもしれません。
今回はお時間をとらせてしまいすみませんでした。

また、最後にまた申し訳ないのですが、今回の、再発の恐れがあるバグは、具体的にはどのようなバグなのでしょうか。
どのようにメモリ上の情報を破壊されていたのかいまいち感覚がつかめないのです。
配列の要素数のあやまりなどによって生じるものなのでしょうか?

アバター
Tatu
記事: 445
登録日時: 15年前
住所: 北海道

Re: 龍神録+タイトルセレクト

#22

投稿記事 by Tatu » 13年前

http://dixq.net/forum/viewtopic.php?f=3&t=10645より
softya(ソフト屋) さんが書きました:それとLoadGraph()とDrawGraph()を同じ関数内に書くとメモリリークを起こします。
徐々にメモリ消費量が増えていき、やがてDXライブラリの管理個数の限界を超えて画像が消えます。
「ゲームプログラミングの館」のあちこちに書いてあると思いますが読み込みと表示の関数は必ず分けるようにして下さい。
今回の原因はload()を何度も呼び出すことにより、メモリリークを起こしたためでしょう。

山中

Re: 龍神録+タイトルセレクト

#23

投稿記事 by 山中 » 13年前

Tatuさん、ご回答ありがとうございます。メモリリークに関して調べてみます。

今回は長い間お付き合いいただき、ありがとうございました。
解決させていただきます。

閉鎖

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