crt0.cについてわかってきましたが・・・・・

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

crt0.cについてわかってきましたが・・・・・

#1

投稿記事 by mi_l » 13年前

先ほどトピックを立てたcrt0.cについてなのですが、検索して過去にも同じ質問をされた方がいるようでしたのでそこで書かれていた改善策を試しましたがどうやら原因が見つかりました。

改善策は、①新しいプロジェクトを作りもういっかいやってみる
        ②コードがおかしいので直してみる
と書かれてありました。

②はどこを直せば?状態でしたので①を試しましたがダメでした・・・
よってコードに問題があることが分かりました。

さらに今回は13章での問題なのでショットの設定の前、つまり、12章のたくさんの敵の行動パターンを作ろうまでをビルドして実行しました。(shot.cpp , shotH.cppをコメントにしてmain.cppの相応するところもコメントにしました)そしたら普通に実行できました。

これらのことからcrt0.cがでるのはshot.cpp , shotH.cppのコードに問題があると断定しました。(この考え方で大丈夫ですよね?)

一応コードも載せます。
shotH.cpp

コード:

#include "../include/GV.h"

//1発だけ、自機に向かって直線移動
void shot_bullet_H000( int n )
{
	int k;
	if( shot[n].cnt == 0 )
	{
		if( shot[n].flag != 2 && ( k = shot_search(n)) != -1 )
		{
			shot[n].bullet[k].knd	= enemy[ shot[n].num ].blknd2;//弾の種類
			shot[n].bullet[k].angle	= shotatan2(n);//角度
			shot[n].bullet[k].flag	= 1;
			shot[n].bullet[k].x		= enemy[ shot[n].num ].x;//座標
			shot[n].bullet[k].y		= enemy[ shot[n].num ].y;//座標
			shot[n].bullet[k].col	= enemy[ shot[n].num ].col;//色
			shot[n].bullet[k].cnt	= 0;//カウンタ
			shot[n].bullet[k].spd   = 3;//スピード
			se_flag[0] = 1;//弾の発射音フラグを立てる
		}
	}
}
shot.cpp

コード:

#include "../include/GV.h"

extern void shot_bullet_H000(int);//shot_bullet_H000(int)の定義

void ( *shot_bullet[SHOT_KND_MAX] )(int) =
{//shot_bullet[SHOT_KND_MAX]アドレスにshot_bullet_H000を格納した
	shot_bullet_H000,
};

//n番目のショットを登録した敵と自機との角度を返す
double shotatan2( int n )
{
	return atan2( ch.y-enemy[shot[n].num].y , ch.x-enemy[shot[n].num].x );
}

//空いてる弾を探す
int shot_search( int n )
{
	int i;
	for( i=0 ; i<SHOT_BULLET_MAX ; i++ )
	{
		if( shot[n].bullet[n].flag == 0 )
		{
			return i;
		}
	}
	return -1;
}

//弾幕の計算
void shot_calc( int n )
{
	int i;
	int max = 0;
	if( enemy[shot[n].num].flag != 1 )//敵が倒されたら
		shot[n].flag = 2;//それ以上ショットを登録しないフラグに変える
	for( i=0 ; i<SHOT_BULLET_MAX ; i++ )//n番目の弾幕データの弾の計算
	{
		if( shot[n].bullet[i].flag > 0 )//その弾が登録されていたら
		{
			shot[n].bullet[i].x += cos( shot[n].bullet[i].angle )*shot[n].bullet[i].spd;
			shot[n].bullet[i].y += sin( shot[n].bullet[i].angle )*shot[n].bullet[i].spd;
			shot[n].bullet[i].cnt++;
			if( shot[n].bullet[i].x<-50 || shot[n].bullet[i].x>FIELD_MAX_X+50 || 
						shot[n].bullet[i].y<-50 || shot[n].bullet[i].y>FIELD_MAX_Y+50 )//画面から外れたら
			{
				if( shot[n].bullet[i].till < shot[n].bullet[i].cnt )//最低消えない時間より長ければ
						shot[n].bullet[i].flag = 0;//消す
			}
		}
	}
	//現在表示中の弾が一つでもあるかどうか調べる
	for( i=0 ; i<SHOT_BULLET_MAX ; i++ )
		if( shot[n].bullet[i].flag > 0 )
			return ;
	if( enemy[shot[n].num].flag != 1 )
	{
		shot[n].flag = 0;//終了
		enemy[shot[n].num].flag = 0;
	}
}

				
			
		
//ショットメイン
void shot_main()
{
	int i;
	for( i=0 ; i<SHOT_BULLET_MAX ; i++ )//弾幕データ計算
	{
		//フラグが立っていて、設定した種類が間違っていなければ(←オーバーフロー対策)
		if(shot[i].flag!=0 && 0<=shot[i].knd && shot[i].knd<SHOT_KND_MAX)
		{
			shot_bullet[ shot[i].knd ](i);//.kndの弾幕計算関数を呼ぶ関数ポインタ
			shot_calc(i);//i番目の弾幕の計算
			shot[i].cnt++;
		}
	}
}
main.cpp

コード:

#define GLOBAL_INSTANCE 
#include "../include/GV.h"

//ループで必ず行う3大処理
int ProcessLoop(){
    if(ProcessMessage()!=0)return -1;//プロセス処理がエラーなら-1を返す
    if(ClearDrawScreen()!=0)return -1;//画面クリア処理がエラーなら-1を返す
    GetHitKeyStateAll_2();//現在のキー入力処理を行う
    GetHitPadStateAll();  //現在のパッド入力処理を行う
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessLoop()==0){//メインループ
		music_ini();//音楽の初期化
        switch(func_state){
            case 0://初回のみ入る処理
                load();        //データロード
                first_ini();//初回の初期化
                func_state=99;
                break;
            case 99://STGを始める前に行う初期化
                ini();
				load_story();
                func_state=100;
                break;
            case 100://通常処理
                calc_ch();    //キャラクタ計算
                ch_move();    //キャラクタの移動制御
                enemy_main();//敵処理メイン
				//shot_main();//ショットメイン
                graph_main();//描画メイン
                stage_count++;
                break;
            default:
                printfDx("不明なfunc_state\n");
                break;
        }
		music_play();//音楽
        if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク
        ScreenFlip();//裏画面反映
    }
    DxLib_End();//DXライブラリ終了処理
    return 0;
}
shot.cpp , shotH.cppはもともと全文コメントにしてありましたがなんとなくコメントにしてない状態で載せました(/* */を取ったということです)
main.cppの上2つのコードに関わるshot_main()はコメントにしてあります。

どこかおかしい、またcrt0.cに引っかかってしまうような箇所はあるでしょうか?
ご指摘お願いします。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: crt0.cについてわかってきましたが・・・・・

#2

投稿記事 by ISLe » 13年前

mi_l さんが書きました:これらのことからcrt0.cがでるのはshot.cpp , shotH.cppのコードに問題があると断定しました。(この考え方で大丈夫ですよね?)
CRT管理メモリ領域の破壊があっても直ぐにはエラーが発生せず、後に破壊された管理メモリ領域が利用されたときにエラーが発生することがあります。
というかむしろ管理メモリ領域が破壊されたとき直ぐにエラーが発生することのほうが稀です。

エラーが発生するまでに実行されているすべてのコード(簡単に言えばぜんぶのコード)を検証する必要があります。
とりあえず、
・配列の範囲外へのアクセス
・初期化されていない一時変数に対するアクセス
が無いかどうか確認すると良いのではないでしょうか。

配布されている13章のコードと比較するのが手っ取り早いですが。

mi_l

Re: crt0.cについてわかってきましたが・・・・・

#3

投稿記事 by mi_l » 13年前

ありがとうございます。試してみます!!

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: crt0.cについてわかってきましたが・・・・・

#4

投稿記事 by Dixq (管理人) » 13年前

ブレイクポイントを張ってどこで落ちたか確認するのが一番手っ取り早いと思います。
落ちる時タイミングはshot_mainを最初に通った時ですか?
shot_mainで落ちると分かっているのであれば、最初にshot_mainにブレイクポイントを張ります(画像参照)
F5キーを押すとそこで処理が止まるので、F11キーでステップインさせます。
その後F10で一行ずつ実行してどこで落ちるか確認して下さい。
関数の中に入りたい時はF11で入れます。こうしてどこで落ちているか、その時変数の値は何かを確認すると原因が分かるでしょう。
添付ファイル
breakpoint.png
breakpoint.png (15.72 KiB) 閲覧数: 2989 回

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: crt0.cについてわかってきましたが・・・・・

#5

投稿記事 by ISLe » 13年前

『ハンドルされていない例外が発生しました』のダイアログで停止したら、デバッガのスタックトレースから呼び出し元を辿れます。
ただし、この手のバグはその時点の呼び出し元が直接の原因ではないことが多いので、目を皿のようにしてコードを追いかけるしか無い場合が多いです。

この手のバグの要因となるコードを発見してくれる機能を持った処理系や解析ツールもあるにはあるのですが。

mi_l

Re: crt0.cについてわかってきましたが・・・・・

#6

投稿記事 by mi_l » 13年前

皆さんありがとうございます。おかげで解決しました。感謝です!!

閉鎖

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