• ベストアンサー

Cプログラムの問題点

C言語で数値計算に関するプログラムを作ったのですが、cygwinで実行すると次のようなコメントが出ます。 5 [main] a 4772 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped) 初心者なので、ところどころミスを発見しては直していたのですが、この問題は調べてみてもプログラムによって異なるみたいなので、質問した次第です。誤りがありましたら、ご指摘ください。

この投稿のマルチメディアは削除されているためご覧いただけません。

質問者が選んだベストアンサー

  • ベストアンサー
noname#144013
noname#144013
回答No.6

こんにちは。#5です。 #5の記述に、一部訂正があります。 変更例のコードの記述部分ですが、以下のように訂正致します。 どうも、すみませんでした。 ■訂正部分(訂正後) ==================== ここは、単純に file を char型配列として、   char file[256];   char *type=".csv";     :     :   printf("Please input file name.");  //←これが抜けていました。   scanf("%s",file);   strcat(file,type); のようにするか、または、file に別のchar型配列のポインタをセットする、   char *file;   char *type=".csv";   char sbuf[256];   file = sbuf;     :     :   printf("Please input file name.");  //←これが抜けていました。   scanf("%s",file);   strcat(file,type); のようにした方が良いかと思われます。 ==================== あと、追加の注意点として scanf での数値入力の際に、数値以外の文字が入力 された場合なども、処理がおかしくなる場合がありますので、入力処理の際に、 正常に入力が行われたかどうかのチェックも入れておいた方が良いかと思います。 例えば、  > printf("X=");scanf("%d",&x); この箇所の場合、  printf("X=");  if(scanf("%d",&x) < 1){    /* 何かしらのエラー処理 */  } といったような感じの処理が考えられます。 ※この場合、scanfの戻り値が、代入されたフィールドの数を返しますので、  その値をチェックして、期待するフィールド分の入力が行われたか否かを  見ています。 以上です。参考になれば幸いです。

noname#201636
質問者

補足

ご指摘の通りです。 だいぶ状況は改善しまして、Method No.1では希望する動作ができましたが、 新たにMethod No.を2または3で入力するとファイル名を入力した後にとまってしまいました・・・。 計算の仕方は違いますが、後の動作は同じはずなんですが・・・。 修正を加えたプログラムはこちらです。uploadr.net/file/b369424cab

その他の回答 (6)

noname#144013
noname#144013
回答No.7

こんにちは。#5、#6です。 > 新たにMethod No.を2または3で入力するとファイル名を入力した後にとまってしまいました・・・。 入力した各種パラメータ(x、y、l、w)の値によっては、ループ処理内でループから 抜け出せない状態になっている為だと思われます。 こちらで試した結果、以下の条件の時にループから抜けない状態(に見える?)に なりました。  <入力パラメータ>  ◎Method No.=2(z=2)の時   x = 1;   y = 1;   l = 0.1;  ◎Method No.=3(z=3)の時   x = 1;   y = 1;   l = 0.1;   w = 1.0; Method No.が 2 または、3 の時の処理は、   do{       :       :     for(i=1;i<=50;i++){       for(j=1;j<=50;j++){         n[i][j]=fabs(a[i][j]-b[i][j]);   //←(*1) (a[i][j] - b[i][j]) の絶対値を計算         if(n[i][j]<=l){m+=1;}      //←(*2) ここで m をカウントアップ       }     }     if(m==2500){        :        :     }else{                  //←(*3) ここに来るのは、m が2500でない時       m=0;                //←(*4) ここで m をリセット       number+=1;       for(i=1;i<=50;i++){         for(j=1;j<=50;j++){           b[i][j]=a[i][j];         }       }     }   }while(m==0);               //←(*5) m が 0 以外でないとループを抜けない のようなループ処理になっていますが、ここで、このループを抜ける条件としては、   (*5)のように、m が 0 以外だった場合 のただ1点だけですので、ループ内で、この条件に達していないと思われます。 また、m の値を変更しているのは、   (*2)の箇所の、m をカウントアップ している箇所ですが、この結果 m が カウントアップされたとしても、 次の if文で、m が 2500 でなかった場合は、   (*4)の箇所で、再び m を 0 にリセット していますので、結局、このループを抜ける条件としては、   m = 2500 になった時のみ ということになります。 ということは、m = 2500 になる条件(=ループを抜ける条件)は、   (*1)、(*2)の部分の、(a[i][j] - b[i][j]) の絶対値の計算結果 n[i][j] の値が、   全て(50×50=2500個)「l の値以下」になった場合のみ ということになります。 以上のように、入力パラメータの値により、上記の条件に永久(?)に達しない 状態が発生していると思われます。 ですので、改めて処理の見直しが必要だと思います。 主な対策としては、 1)入力値に制限を設ける   #3さんが言われているように、入力値に上限値・下限値などの制限値を設けて、   入力値が、その範囲内にあるか否かなどのチェックを行い、範囲外だったら、   再び入力を行うなどの処理を行う。 2)ループ処理の脱出条件を見直す    ・ループ処理内の各種演算の見直し    ・抜け出す条件の見直し    ・ある値について、想定外の値になったらループを抜ける   などの対策を行う。 3)デバッグ用に「ログファイル」の出力処理を入れる   ループ内での各種データの途中経過を確認する意味で、ループ内で各種データ   の値をファイル(=ログファイル)に書き出す処理を追加する。   このログファイルを見ることで、処理がどこまで正常に行われているかを確認   できると思います。 4)デバッグツールを使用する   cygwinの環境で使用できるものがあるかどうか判りませんが、ソースレベルで   ブレークポイントを設定できたり、ステップ単位で実行できるデバッグツールを   利用して処理を追えるようにするのも一つの手段だと思います。 などの方法が考えられます。 あと、基本的な事ですが、ソースに「コメント」を付けるようにした方が良いかもしれ ません。 コメントを付けることで、頭の中で処理の再確認・整理ができるので、以外とバグ発見 の手助けになる場合があります。 それと、インデントをキチンと整形された方が、ネストレベルのズレなどがチェックできて 良いかと思います。 <補足> 余談ですが、デバッグ作業は大変かと思いますが、作業を進めるにあたってあまり 焦らずに、どこまで正常に実行できているかなどを、地道にじっくりと追いかけながら (机上デバッグも含めて)作業を進めれば、いずれ解決に繋がるかと思います。 それと、あまり根を詰めても、精神的にも疲れるだけで効率は上がりませんので、 こまめに休憩するなどの息抜きをして、気分転換を図った方が良いかと思います。 ※経験上、全く関係ない事をしている最中に突然、解決策を思い付くといったよう  なことがたまにあります。 ご健闘をお祈り致します。頑張って下さい。

noname#201636
質問者

お礼

ご回答いただいた通りの動作を希望していました。 結局、ERRORには入力してはいけない数字があったようです。 また、計算式も一部間違えていました。 3度にわたり、回答いただきありがとうございました。

noname#144013
noname#144013
回答No.5

こんにちは。 他の要因もあるかもしれませんが、少なくとも > 5 [main] a 4772 _cygtls::handle_exceptions: Error while dumping state > (probably corrupted stack) > Segmentation fault (core dumped) のエラーが発生するのは、下記部分が原因だと思われます。 > char *file; >   : >   : > printf("Please input file name.");scanf("%s",&file); > strcat(file,type); ここで file に出力ファイル名を入力&設定することを想定されているようですが、  1)まず、変数 file は、char *file;(char型のポインタ変数)として宣言されていますが、    このポインタ変数には、なにもポインタがセットされていません。    そのため、file の中身(=アドレス)は不定な値のままです。  2)そして、1)の件とは別の話ですが、scanf("%s",&file); の & が余分です。 ですので、このまま実行すると不正なエリアにアクセスすることになり、 今回のように、例外エラーなどが発生する可能性があります。 ここは、単純に file を char型配列として、   char file[256];   char *type=".csv";   scanf("%s",file);   strcat(file,type); のようにするか、または、file に別のchar型配列のポインタをセットする、   char *file;   char *type=".csv";   char sbuf[256];   file = sbuf;   scanf("%s",file);   strcat(file,type); のようにした方が良いかと思われます。 それと、ファイルをオープンしている部分、 >  tofile=fopen(file,"w"); の箇所は、fopenの戻り値をチェッしてファイルオープンが成功したか否かを 見る「エラー処理」を入れた方が良いかと思います。 以上です。見当違いであればすみません。 参考になれば幸いです。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

画像じゃなくてソースのテキストファイルをそのままアップしてもらったほうがいいです。(インデントもエディタで直せますし実行も出来るので)

noname#201636
質問者

補足

ではこちらのほうにアップしておきます。uploadr.net/file/37bb996449 画像と多少異なるのは、少し手直ししたためです。

回答No.3

long doubleの配列要素数少なくしたらどうなります? (auto変数=stackが、1単位4Byteだと31K、8Byteだと62Kになる) それと、XYの入力に制限つけないと、w1、w2の算出とそれを使用した処理でとんでもないとこアクセスしますよ。

noname#201636
質問者

補足

そうですね。XとYはそれぞれ数字1字ですので、制限つけた方がいいですね。

回答No.2

ちゃんと見たわけではありませんけど。 m!=40 とか m==40 あたりなんじゃないかと思うんですが。 mの値をデバッガとかテキストファイルとかにダンプして 値を見てみたらいかがでしょうか。 実は、m が 40 になることが無いとか。 m>=40 とかじゃ駄目なんですかね。

noname#201636
質問者

お礼

条件のミスも原因の1つでした。補足で間違えていますが、m=2500でした。 ありがとうございました。

noname#201636
質問者

補足

そうですね。m=40じゃなくてm=250でした。ただ、そこを直しただけじゃダメみたいです。

回答No.1

無限ループに陥るような再帰呼び出しをしたとか、配列外をアクセスしたとかではないでしょうか?

noname#201636
質問者

お礼

結果的に不当な入力による無限ループも原因の1つでした。 ありがとうございました。

noname#201636
質問者

補足

無限ループに近い動作にはなると思います。 (プログラムを画像化しましたが見えませんね。imagepot.net/view/124568753881.jpgに同じものを載せました。)

関連するQ&A