ハンドルされていない例外の再発

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

ハンドルされていない例外の再発

#1

投稿記事 by SDD » 5年前

毎度すみません。以前http://dixq.net/forum/viewtopic.php?f=3&t=15492にて、ハンドルされていない例外
のことで質問をした者です。申し訳ありませんが、テンプレやコードの詳細は上記のURLをたどってみていただけると幸いです。(まだトピックの一覧の1ページ目に残っているので
それを見たほうが早いかもですが)

今回、上記の問題が再発してしまったため、またトピックを立たせていただきました。

以前のトピックにて問題が解決され、今朝までは思い通りに動いていたのですが、あることをした結果、また「ハンドルされていない例外」や、
「Stack around the variable 'data' was corrupted.」などがでてくるようになってしまいました。

順を追って、きっかけや症状を説明します。

早朝のことなので、すこしうろ覚えなのですが、

1、敵オブジェクトを作る際、何体までなら重くならないかを調べたかったため、敵の数を極端にふやした。(たしかENEMY_NUMを600にした。当然、CSVも600行。馬鹿なことやったなあと思います。)
2、フルスクリーンモードで実行した。結果、重くなりすぎて、フリーズした。待っても、プログラムを終了させようとしても無駄だったため、仕方なくPCを強制終了した。
3、起動し、ENEMY_NUMを5に戻した。当然CSVも5行に。
4、実行したら、「Stack around the variable 'data' was corrupted.」がでるようになった。
5、コードはそこ以外変えていない(はず)
6、ステップ実行でnを調べると、なぜかn==5にまでなっていた。(前回はn==6にまでなっていたが、原因はCSVの打ち損じミスだった)結果data[5]にまでなってしまって、ENEMY_NUMをオーバーしている.
ここがエラーの原因なのはわかるが、もとに戻したはずなのになぜこうなるかわからない。
7、600行にしたり、5行にもどした際、また何かミスがあったのかとCSVをチェックしても異常は見当たらない。
8、ためしに、CSVファイルを一度消し、龍神録プロジェクトのdatからコピーして5行に変更したCSVファイルを入れなおした。
9、結果、一度だけ異常なくプログラムが動いたが、ためしに、新しくしたCSVデータを、1行目のyの値だけ数値を変えて(特にその変更に意図はない)実行した結果、再び同じエラーが出るようになった。
10、いくらリビルドなどしても、CSVのテキストを見直しても、うまく行かず、質問しました。

正直、まったく検討がつきません。毎度すみませんが、アドバイスのようなものをいただきたいです。
どうかよろしくお願いします。

初級者
記事: 200
登録日時: 9年前

Re: ハンドルされていない例外の再発

#2

投稿記事 by 初級者 » 5年前

このコード

このcsv
を使うと、必ず再発する
という
コード

csv
を提示するのが
よい、と思います。

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

Re: ハンドルされていない例外の再発

#3

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

今までバグが発覚しなかっただけで潜在バグが表面化しただけです。
根本的にバグを散らないと何時迄も付きまといそうです。
まぁ、完全にcsvの読み込みを理解してエラーになる部分のガードを増強して作りなおしたほうが良いんでしょうね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#4

投稿記事 by SDD » 5年前

ソフト屋さん、敵をつくる構造そのものに難ありでしょうか。
それとも、実際に問題のある、ロード関数だけを作り直すのが無難でしょうか。

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

Re: ハンドルされていない例外の再発

#5

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

これから何度も作りなおすと思いますので、その時ベストな方法で出来ていれば問題無いと思います。

>それとも、実際に問題のある、ロード関数だけを作り直すのが無難でしょうか。

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

SDD

Re: ハンドルされていない例外の再発

#6

投稿記事 by SDD » 5年前

問題は、nがENEMY_NUMを超えてしまうことということしか思い浮かびません・・・。
ロード関係の処理は勉強中なのですが、ロード周りの根本は龍神録のソースから持ってきたものなので、
やはり、CSVの何らかのミスや龍神録との相違点である、dataという構造体変数関連でミスをしているのか・・・。

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

Re: ハンドルされていない例外の再発

#7

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

なぜnが超えてしまうかが調べられていません。
つまり、ガードが甘い読み込み処理なので、問題点を探して下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#8

投稿記事 by SDD » 5年前

自分で考えなければならないことなので、今すぐ安直に、問題の根本的な回答を伺うことはしませんが、
不躾な質問になってしまうのですが、ソフト屋さんにとって、今回のエラーをなくす方法やああすればいいのにといったものが明確にあり、それは「自分で考えろ」ということなのでしょうか。
失礼な質問ですみません。

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

Re: ハンドルされていない例外の再発

#9

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

SDD さんが書きました:自分で考えなければならないことなので、今すぐ安直に、問題の根本的な回答を伺うことはしませんが、
不躾な質問になってしまうのですが、ソフト屋さんにとって、今回のエラーをなくす方法やああすればいいのにといったものが明確にあり、それは「自分で考えろ」ということなのでしょうか。
失礼な質問ですみません。
元(龍神録)からの問題ですが、読み込み処理にイレギュラーな値や動作のガードがありませんので、何か問題があればこんな風に困ることになります。
何度か、それらしいことは書いていますよ。

>つまり、ガードが甘い読み込み処理なので、問題点を探して下さい。
>まぁ、完全にcsvの読み込みを理解してエラーになる部分のガードを増強して作りなおしたほうが良いんでしょうね。

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

SDD

Re: ハンドルされていない例外の再発

#10

投稿記事 by SDD » 5年前

ガードが甘いことが問題・原因ならば、なぜnがENEMY_NUMを超えてしまうのかを把握して、ガードを強めさえすれば(nがENEMY_NUMを超えないようにする)
解決し、正常に動くという解釈で良いのでしょうか。

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

Re: ハンドルされていない例外の再発

#11

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

SDD さんが書きました:ガードが甘いことが問題・原因ならば、なぜnがENEMY_NUMを超えてしまうのかを把握して、ガードを強めさえすれば(nがENEMY_NUMを超えないようにする)
解決し、正常に動くという解釈で良いのでしょうか。
そのガードを入れる過程で潜在バグがあればイレギュラーな動作としてガードが働き問題が表面化するはずですので、問題は解決するはずです。

ただ、今現在問題が再現している状況ならば、潜在バグの部分を見つける事は難しくないはずです。
ちゃんと読み込み処理のコードの動作をデバッグで順序良く追いかけれているのなら気づく問題だと思います。
なぜなら、問題の有る所でイレギュラーな動作をしたりイレギュラーな値が読み込まれるはずですから。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#12

投稿記事 by SDD » 5年前

わかりました。
またしばらく、見ていこうと思います。
正直、このトピックで最初に書いたように、下手な実験をしたせいで色々おかしくなったのか
と不安に思っていたのですが、今までたまたまうまくいっていただけならまだなんとかしようがあるので、
とりあえず致命的なバグを発見することにつながってよかったと思います。

すみませんが、念のため、まだ未解決にしておきます。

SDD

Re: ハンドルされていない例外の再発

#13

投稿記事 by SDD » 5年前

すみません、今度のトラブルもまたCSVテキストが原因でした。最後の行に続き、空白の行が何行かあり、それをしっかりと消すと元通りに動くように
なりました。(いかんせん空白なため、キーを押してカーソルを移動させないと気付けなかった)CSVをテキストエディタでいじくることはあんまり良くないようです。
一度、わざと、行を同じように乱して、実行すると、それまでと同じエラーメッセージが出て、その行を元通りに正してやると、また正しく動き始めました。
600行増やし、それを5行に戻した際、余計な空白を消しきれてなかったのだと思います。

しかし、やはり脆弱なコードなため、ガードの処理を考えています。
考えた結果のガードのコードを評価していただきたいので、まだ未解決とします。

SDD

Re: ハンドルされていない例外の再発

#14

投稿記事 by SDD » 5年前

ガードの処理を考えていたのですが、なかなかうまくいかず、わからなくなりました。
読み込み処理の構造上、必ずnはENEMY_NUMと等しくなるため(nは0からはじまるため、ENEMY_NUMである5はnでいうと4であるが、nが5になった後読み込みを行う前にテキスト
を閉じるようになってる)、

コード:

if(n>ENEMY_NUM){//nが実際にENEMY_NUMを超えたら
//ここに有効な処理をかきたい
}
という風なところまで考えたのですが、こういうとき、有効なオーバーフロー対策の処理はどのようなものでしょうか。
ヒントやアドバイスをいただけたらと思います。

SDD

Re: ハンドルされていない例外の再発

#15

投稿記事 by SDD » 5年前

一応、再度コードを貼ります。

コード:


 
void EnemyControl::Make_Enemy(){
    EnemyData data[ENEMY_NUM];
    int n,num,i,fp;
    char fname[]={"story1.csv"};
    int input[64];
    char inputc[64];
 
    fp = FileRead_open(fname);//ファイル読み込み
    if(fp == NULL){
        printfDx("read error\n");
        return;
    }
    for(i=0;i<2;i++)//最初の2行読み飛ばす
        while(FileRead_getc(fp)!='\n');
 
    n=0 , num=0;
    while(1){
        for(i=0;i<64;i++){
            inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
            if(inputc[i]=='/'){//スラッシュがあれば
                while(FileRead_getc(fp)!='\n');//改行までループ
                i=-1;//カウンタを最初に戻して
                continue;
            }
            if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                inputc[i]='\0';//そこまでを文字列とし
                break;
            }
            if(input[i]==EOF){//ファイルの終わりなら
                goto EXFILE;//終了
            }
        }
        switch(num){
                        case 0: data[n].cnt      =atoi(inputc);break;
                        case 1: data[n].pattern  =atoi(inputc);break;
                        case 2: data[n].knd      =atoi(inputc);break;
                        case 3: data[n].x        =atof(inputc);break;
                        case 4: data[n].y        =atof(inputc);break;
                        case 5: data[n].sp       =atof(inputc);break;
                        case 6: data[n].bltime   =atoi(inputc);break;
                        case 7: data[n].blknd    =atoi(inputc);break;
                        case 8: data[n].col      =atoi(inputc);break;
                        case 9: data[n].hp       =atoi(inputc);break;
                        case 10:data[n].blknd2   =atoi(inputc);break;
                        case 11:data[n].wait     =atoi(inputc);break;
                        case 12:data[n].item_n[0]=atoi(inputc);break;
                        case 13:data[n].item_n[1]=atoi(inputc);break;
                        case 14:data[n].item_n[2]=atoi(inputc);break;
                        case 15:data[n].item_n[3]=atoi(inputc);break;
                        case 16:data[n].item_n[4]=atoi(inputc);break;
                        case 17:data[n].item_n[5]=atoi(inputc);break;
        }
        num++;
        if(num==18){
            num=0;
            n++;
        }
    }
EXFILE:
    FileRead_close(fp);
 
    //敵オブジェクト生成
    for(int i=0;i<ENEMY_NUM;i++){
        enemy[i]=new Enemy(data[n].cnt,data[n].pattern,data[n].knd,data[n].x,
            data[n].y,data[n].sp,data[n].bltime,data[i].blknd,data[n].col,
            data[n].hp,data[n].blknd2,data[n].wait,data[n].item_n);
    }
}
 
 

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

Re: ハンドルされていない例外の再発

#16

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

エラーですのでエラーログを画面に表示して、ログファイルを出して終了すべきかと思います。Log.txtに書き出す方法もあります。
つまり、エラーで戻るのですがC++ならthrowしてはどうでしょう。
あと、列のデータの個数やデータ型が合わない時もエラーにすべきです。

【補足】
戻り値をエラーにして返す方法もあります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#17

投稿記事 by SDD » 5年前

返信ありがとうございます。

条件をさらに厳しくするべきなのはわかりました。

とりあえず、当初の条件であった「nが超えないように」というのに絞ってやってみたところ、例外処理が不慣れなこともあって、
なぜかスルーしてしまいます。(スローしてほしいのに)
わざと、CSVに無駄な空白を持たせ、nがENEMY_NUMを超えるようにし、例外されていないハンドルを起こすと、例外処理を無視して「ハンドルされていない例外」という
いつものエラーが起きるだけでした。

記述に問題があるからこの結果なのでしょうが、間違いがわかりません・・・。

コード:

void EnemyControl::Make_Enemy(){

	EnemyData data[ENEMY_NUM];

	int n,num,i,fp;
	char fname[]={"story1.csv"};
	int input[64];
	char inputc[64];

	fp = FileRead_open(fname);//ファイル読み込み
	if(fp == NULL){
		printfDx("read error\n");
		return;
	}
	for(i=0;i<2;i++)//最初の2行読み飛ばす
		while(FileRead_getc(fp)!='\n');

	n=0 , num=0;
	try{//例外処理
		while(1){

			if(n>ENEMY_NUM){
				throw(1);
			}
			for(i=0;i<64;i++){
				inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
				if(inputc[i]=='/'){//スラッシュがあれば
					while(FileRead_getc(fp)!='\n');//改行までループ
					i=-1;//カウンタを最初に戻して
					continue;
				}
				if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
					inputc[i]='\0';//そこまでを文字列とし
					break;
				}
				if(input[i]==EOF){//ファイルの終わりなら
					goto EXFILE;//終了
				}
			}
			switch(num){
						case 0: data[n].cnt      =atoi(inputc);break;
						case 1: data[n].pattern  =atoi(inputc);break;
						case 2: data[n].knd      =atoi(inputc);break;
						case 3: data[n].x        =atof(inputc);break;
						case 4: data[n].y        =atof(inputc);break;
						case 5: data[n].sp       =atof(inputc);break;
						case 6: data[n].bltime   =atoi(inputc);break;
						case 7: data[n].blknd    =atoi(inputc);break;
						case 8: data[n].col      =atoi(inputc);break;
						case 9: data[n].hp       =atoi(inputc);break;
						case 10:data[n].blknd2   =atoi(inputc);break;
						case 11:data[n].wait     =atoi(inputc);break;
						case 12:data[n].item_n[0]=atoi(inputc);break;
						case 13:data[n].item_n[1]=atoi(inputc);break;
						case 14:data[n].item_n[2]=atoi(inputc);break;
						case 15:data[n].item_n[3]=atoi(inputc);break;
						case 16:data[n].item_n[4]=atoi(inputc);break;
						case 17:data[n].item_n[5]=atoi(inputc);break;
			}
			num++;
			if(num==18){
				num=0;
				n++;
			}
		}
	}

	catch(int err){
		MessageBox(NULL,"nがENEMY_NUMを超えました。CSVを確認してください","メッセージ",MB_OK);
		return;
	}
EXFILE:
	FileRead_close(fp);

	//敵オブジェクト生成
	for(int i=0;i<ENEMY_NUM;i++){
		enemy[i]=new Enemy(data[i].cnt,data[i].pattern,data[i].knd,data[i].x,
			data[i].y,data[i].sp,data[i].bltime,data[i].blknd,data[i].col,
			data[i].hp,data[i].blknd2,data[i].wait,data[i].item_n);
	}
}


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

Re: ハンドルされていない例外の再発

#18

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

失礼。見逃してました。
ヒントは添字は0からですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#19

投稿記事 by SDD » 5年前

コード:

	if(n>ENEMY_NUM){
              throw(1);
	}
のことでしょうか・・・。
if(n>=ENEMY_NUM)、という風にすれば、メッセージボックスが出てきてくれたのですが、

コード:

                if(input[i]==EOF){//ファイルの終わりなら
                    goto EXFILE;//終了
                }
の処理の時点ではnが5になっているので、その書き方にすると、テキストが正しくてもメッセージボックスが出てきてしまうようです。

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

Re: ハンドルされていない例外の再発

#20

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

> の処理の時点ではnが5になっているので、その書き方にすると、テキストが正しくてもメッセージボックスが出てきてしまうようです。

すいません、意味不明です。
if(n>=ENEMY_NUM)、で弾いたら、そこから下には行かないはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#21

投稿記事 by SDD » 5年前

えーと・・・
指摘されたところが(添字のこと) if(n>ENEMY_NUM)だと思ったので、
if(n>=ENEMY_NUM)とすると、例外の判定のところに来たときはnが5になっているので弾かれてしまうため、n[4]までただしくロードされていても、メッセージボックスの処理まで飛んでしまう
と言いたかったのですが、まだ語弊があるかもしれません

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

Re: ハンドルされていない例外の再発

#22

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

あぁ、じゃあ先にEOFその他の入力処理してからif(n>=ENEMY_NUM)でい良いのでは? 問題がありますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#23

投稿記事 by SDD » 5年前

EOF関連の文より下にその判定文を持ってくるということですよね。
ついさっき、それをやって思い通りに動いたため、それでも問題があるかどうか聞きたかったのですが、
問題はない・・・ということでよいのでしょうか。

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

Re: ハンドルされていない例外の再発

#24

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

SDD さんが書きました:EOF関連の文より下にその判定文を持ってくるということですよね。
ついさっき、それをやって思い通りに動いたため、それでも問題があるかどうか聞きたかったのですが、
問題はない・・・ということでよいのでしょうか。
自分で考えて、自分で検証して、これこれこういう結果で問題無いと思います。
まで持っていかないと、エラー処理を自分で組んでいることになりませんので、この時点での答えは差し控えます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

SDD

Re: ハンドルされていない例外の再発

#25

投稿記事 by SDD » 5年前

すみません。返信するのを忘れておりました。
とりあえず解決といたします。

閉鎖

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