質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

13997閲覧

Bus error:10の原因を知りたい

houki

総合スコア22

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/08/15 15:04

編集2018/08/16 01:04

前提・実現したいこと

vscodeにて、実行すると Bus error:10がなぜ表示されるのを知って、出ないようにしたい。

発生している問題・エラーメッセージ

Bus error:10

該当のソースコード

C

1for(;jdg_t_c[times]<first[times]+gl_del_count_c[times];jdg_t_c[times]++) 2 3for(;jdg_t_c[times]-first[times]<4;jdg_t_c[times]++) 4 5

c

1全体を載せると3000行を超えるので、問題の関数内のところにしています。 2int othello_AI(int n){ 3 4 static int jdg_t_c[10]={0};//for添字 5 static int first[10]={0};//for添字 6 static int times=0;//for添字 7 int count=0,counta=0, countb=0, countc=0, countd=0, counte=0, tmp;//for添字 tmpは並び替えの時に一時的に入れておくための変数。 8 static int k[10][100]={{0},{0}};//for添字 9 static int jdg_GUIDE_num[10][1000]={{0},{0}};//for 次の手のGUIDEの数 10 static int jdg_minmax_dual_num[10][1000]={{0},{0}};//for jdg_GUIDE_numの最大最小を入れておく。 11 int jdg_est_num[10][1000]={{0},{0}};//for 各timesでのjdg_minmax_numの組み合わせを入れる。 12 int jdg_total_dual_count[10]={0}; 13 static int jdg_minmax_num[10][100][1000]={{0},{0},{0}};//for 最小最大の被った数の保持する。 14 static int gl_del_count_c[10]={0};//for gl_del_countのコピー 15 static int gl__x_c[10][40],gl__y_c[10][40];//for gl__x,gl__yのコピー 16 static int jdg_count[10]={0};//for添字→ 関数の出入りの1かたまりの数をそれぞれ記録する。グループ分けとしての変数。 17 18 static int c1_mas[SIZE][SIZE]={ 19 {1,1,1,1,1,1,1,1,1,1}, 20 {1,0,0,0,0,0,0,0,0,1}, 21 {1,0,0,0,0,0,0,0,0,1}, 22 {1,0,0,0,0,0,0,0,0,1}, 23 {1,0,0,0,0,0,0,0,0,1}, 24 {1,0,0,0,0,0,0,0,0,1}, 25 {1,0,0,0,0,0,0,0,0,1}, 26 {1,0,0,0,0,0,0,0,0,1}, 27 {1,0,0,0,0,0,0,0,0,1}, 28 {1,1,1,1,1,1,1,1,1,1}, 29 }; 30 static int c2_mas[SIZE][SIZE]={ 31 {1,1,1,1,1,1,1,1,1,1}, 32 {1,0,0,0,0,0,0,0,0,1}, 33 {1,0,0,0,0,0,0,0,0,1}, 34 {1,0,0,0,0,0,0,0,0,1}, 35 {1,0,0,0,0,0,0,0,0,1}, 36 {1,0,0,0,0,0,0,0,0,1}, 37 {1,0,0,0,0,0,0,0,0,1}, 38 {1,0,0,0,0,0,0,0,0,1}, 39 {1,0,0,0,0,0,0,0,0,1}, 40 {1,1,1,1,1,1,1,1,1,1}, 41 }; 42 43 first[times]=jdg_t_c[times]; 44 45 //for mas[SIZE][SIZE]のコピー 46 othello_mas_c(c1_mas, c2_mas, times); 47 //gl_del_countにGUIDEの個数をコピーするため。times==0の時はすでにもう入っている。 48 switch(times){ 49 case 0: 50 break; 51 default: 52 del(); 53 break; 54 } 55 //for mas[SIZE][SIZE]にコピーし直す。 56 othello_mas_c_r(c1_mas, c2_mas, times); 57 //for gl_del_count_cにgl_del_countをコピー 58 othello_gl_del_count_c(gl_del_count_c, times); 59 //for gl__x[],gl__y[]の座標のコピー これを行うには事前にdel()を呼び、gl_del_countにGUIDEの個数を入れておかなければならない。 60 othello_gl__xy_c(gl__x_c, gl__y_c, times); 61 62 63 if(n%2==0){ 64 65 for(;jdg_t_c[times]-first[times]<gl_del_count_c[times];jdg_t_c[times]++){ 66 printf("&w"); 67 switch(mas[gl__y_c[times][k[times][jdg_count[times]]]][gl__x_c[times][k[times][jdg_count[times]]]]){ 68 case GUIDE: 69 printf("&w+"); 70 gl_x=gl__x_c[times][k[times][jdg_count[times]]]; 71 gl_y=gl__y_c[times][k[times][jdg_count[times]]]; 72 73 othello_gl_del_count_c_r(gl_del_count_c, times); 74 othello_gl__xy_c_r(gl__x_c, gl__y_c, times); 75 del(); 76 mas[gl__y_c[times][k[times][jdg_count[times]]]][gl__x_c[times][k[times][jdg_count[times]]]]=WHITE; 77 78 jdg_GUIDE_num[times][jdg_t_c[times]]=10000*jdg_t_c[times]+100*jdg_count[times]+put1(n+1); 79 80 if(times<2){ 81 times++; 82 othello_AI(n+1); 83 times--; 84 } 85 86 othello_mas_c_r(c1_mas, c2_mas, times); 87 88 break; 89 } 90 k[times][jdg_count[times]]++; 91 } 92 93 } 94 else{...

試したこと

どの配列もstatic int型で、定義の時点で、全てに0を格納しており、上記の場合も、条件を満たすように何かしらの整数が入っています。

1つ目のforの前に//を加えると、Bus errorは表示されなくなり、原因はここにあると判断しています。また、条件部分のgl_del_count_c[times]を消すと、Bus errorは表示されなくなります。しかし、別の方法で、2つ目のforように適当な整数4とした場合、Bus errorが表示されます。

補足情報(FW/ツールのバージョンなど)

vscode

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nob.

2018/08/15 21:57

エラー発生時のtimesの値を確認して下さい。
rubato6809

2018/08/15 23:31 編集

バスエラーが、このfor文で起きたことは確認できていますか? このfor()文がエラーの要因であるのは間違いないでしょうが、エラー自体は別の場所で起きている可能性があるのではないですか? for文は jdg_t_c[times] の値を増やしています。値が増えた後、jdg_t_c[times] の値を使う場所付近がエラーを起こしている可能性があると思います。
houki

2018/08/16 00:15

エラー発生時のtimesは0です。
houki

2018/08/16 00:17

gl_del_count_c[times]を消すと、バスエラーが出てこないからといって、主原因がgl_del_count_c[times]とは限らないんですね。。。調べてみます
houki

2018/08/16 00:23

static int jdg_t_c[10]={0}; static int times=0; static int gl_del_count_c[10]={0}、static int first[10]={0};としています。
rubato6809

2018/08/16 00:26

そろそろ、そうした情報は質問に追記してください。jdg_t_c[times] の値を使う場所付近も示してもらえると良いです。
guest

回答2

0

ベストアンサー

どこが悪いのか、私にはわかりません。
一番の対処法は、デバッガを使うことです。デバッガで、

  • バスエラーを起こした箇所(命令、ソースコード上の位置)を特定する

ことです。さらに、

  • 何番地をアクセスしてエラーになったのか
  • その時点の各変数の値はいくつか

を調べることです。

さて、バスエラーは割り当てられたメモリを逸脱してアクセスしたということ。バッファオーバーランが大々的に起こったのでしょう。
プログラムはたくさんの配列を使っているので、例えば int arr[10] と定義したのに、 arr[100] だとか arr[-1000] のような、ともかく配列の添字が範囲を大きく逸脱したのだろうと思います。

提示されたコードを見て予想したことを書きます。

1.
プログラムは、配列のどこかの値を、別の配列の添字として使うパターンだらけです。例えば int k[10][100] に対して

C

1 k[times][jdg_count[times]]++;

という行があります。もし jdg_count[times] の値が100以上になれば、その時点でオーバーランです。バスエラーを起こさなくてもバグです。

添字が範囲を超えれば、他のメモリを書き換えるので、その後何が起こっても不思議はありません。

2.

C

1 for(;jdg_t_c[times]-first[times]<gl_del_count_c[times];jdg_t_c[times]++){

の部分、

条件部分のgl_del_count_c[times]を消すと、Bus errorは表示されなくなります。しかし、別の方法で、2つ目のforように適当な整数4とした場合、Bus errorが表示されます

ここを私は

C

1 for (;jdg_t_c[times] - first[times] < 0; 2 jdg_t_c[times]++) {

ならエラーにならない、

C

1 for (;jdg_t_c[times] - first[times] < 4; 2 jdg_t_c[times]++) {

ならエラーになる、と理解しました。合ってますか?

関数の先頭で first[times] = jdg_t_c[times]; としてるので、

  • 上のforループなら jdg_t_c[times] の値は変化せずループが終わるが
  • 下のforループだと jdg_t_c[times] の値は first[times] + 4 まで値が増えます。

違いは僅かですが、それがバスエラーに結びつくなら、違いが増幅されるからではないか?と予想できます。すると jdg_t_c[times] の値を10000倍した項がある

C

1 jdg_GUIDE_num[times][jdg_t_c[times]]=10000*jdg_t_c[times]+100*jdg_count[times]+put1(n+1);

が目にとまります。ここは jdg_GUIDE_num[][] のどこかに値を代入するだけですが、さらにその値を別の配列の添字として使っていたら、あやしい。

3.
再帰呼出しには問題無いか?
おそらく次回は else 以下の省略されている部分を実行するのでしょう。そのコードは示されていませんので。

C

1 if(times<2){ 2 times++; 3 othello_AI(n+1); 4 times--; 5 }

投稿2018/08/16 04:52

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

houki

2018/08/16 05:30

rubato6809さん、最初の回答者のところで返信したのですが、Bus errorの原因箇所が、同じ関数内ではあるのですが、ここには載せていないところのコード部分がバッファオーバーランしていたようで、訂正したところ今はBus errorが表示されることなくプログラムが実行できました。 一応、オセロのAIとしてはまだ完成はしていないのですが、kの2つ目の箱の大きさは大きくしようと思います!
houki

2018/08/16 05:32

あと、デバッグの仕方(そもそもデバッグの設定)ができていないので、今まで自力で探していました。 また別の質問でvscodeのc言語におけるデバッグの設定の仕方諸々のやり方を聞こうと思います。
guest

0

jdg_t_cの配列のサイズとtimesの内容をチェックしてみましょう

おそらく、times は配列のサイズから外れていて、不正アクセスとなってます

投稿2018/08/15 22:00

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

houki

2018/08/16 00:22

static int jdg_t_c[10]={0}; static int times=0; としており、timesは0~2の整数の範囲で変化します。 これは不正アクセスになっていますか?
y_waiwai

2018/08/16 00:23

それではなってません。あくまで、そのバスエラーが出るときのtimesの値を見てみてください
y_waiwai

2018/08/16 00:25

firstとgl_del_count_cの定義はどうなってますか?というより、ソース全体を提示してくださいな
houki

2018/08/16 16:03 編集

消しました
rubato6809

2018/08/16 00:44

コードは、コメントではなく、質問に追記する形で示してください。もちろん、コードタグで囲むことをお忘れなく。
rubato6809

2018/08/16 00:48

デバッガを使えばよいのですが、それが難しい場合もあります。 > 3000行を超える ひとつの手は、エラー発生に関係ないコードを削除しまくって、エラーが発生する最小のコードにすることです。それはそのまま原因を絞り込むことになります。
houki

2018/08/16 01:08

訂正しました。教えていただきありがとうございます。
houki

2018/08/16 01:08

関係ないコードのコメントアウトするのと、消去するのとでは結果が全く異なりますか?
rubato6809

2018/08/16 01:22 編集

コメントアウトでも同じです。 ただ、要らないコードをバッサリ消すと、すっきり見通しが良くなりわかりやすくなることと、時にコメントアウトしたつもりがそうなっておらず意図しない結果になることもあるので、消去をお勧めします。 つまり、まず使うファイルは保存しておく、それから、コメントアウトしてエラーが再現するならバッサリ消す、再現しなくなるとか他の不具合が出るようになるならコードを復活する、これを繰り返します。 それにしても、スゴいコードですね。よく、こんなコードが書けましたね。。。
houki

2018/08/16 01:24

なるほど、確かにそうかもしれませんね。まだ経験値が足りないので、これからrubato6809さんのやり方をしていこうと思います!
houki

2018/08/16 01:28

その言葉を褒め言葉として受け取ってい良いのでしょうか? オセロをオセロのプログラムを組み終わり、そこに3手先を読んだ上で打つAIを作っているところで、Bus errorが出てしまって、、、 もっと簡単な探索方法があるに違いないのですが、まだ配列とや関数のことぐらいしか知らないので、陳腐なプログラムになっています笑
houki

2018/08/16 04:25 編集

rubato6809さんが初めにおっしゃった通り、エラー自体はここには載せていない別のところで、起こっていたようでした。親切な対応ありがとうございました。
houki

2018/08/16 09:52

笑 もちろんAIの関数自体が3000行あるわけではありません。 しかし今作っているAIの関数は500くらいあるのですが。。。 なるべく細かく分割して、小さな関数の集まりみたいにするのが理想なのでしょうか?
yumetodo

2018/08/16 10:05 編集

関数を適切に分けたり、構造体や他言語ならクラスを積極的に活用したり、そもそも自分でコードを書かないですでにあるライブラリの関数をよく調べて使うとかそういうことが必要でしょうね。さもないとバグが頻発します。 とくにCはbuffer overrunしやすいので責任の所在が明確にならないとデバッグしようもありません。 一つの指標としては、即座に最小コードを作れるようなコードはテストもしやすいし(単体テスト、大事、絶対)、バグも少ないです。テスト駆動開発(TDD)なんて言葉もあるくらいです。テストしやすいということは必然的に関数に見えない入力と出力が減るということなのでわかりやすいコードになります。 なお私はCが面倒くさくってやってられなかったのでC++使っています。やりたいことと人によって適切な手段は異なりますが。
houki

2018/08/16 10:06

構造体。。。まだ習っていないのですが、構造体がよりコードを見やすくスッキリさせてくれるのですね。今夏中に勉強しようと思います。まだまだ知識がないので、1つ1つ手で入力するというが形でプログラミングを学んでいます。 ありがとうございます。
houki

2018/08/16 10:27

ありがとうございます。じっくり目を通することにします。
rubato6809

2018/08/16 12:23

>その言葉を褒め言葉として受け取ってい良いのでしょうか? 両面あります。 最終成果物として、あのスタイルはいただけません。わかりにくく保守性がかなり悪い。 しかし、これだけややこしいことをめげずに書けて動かせるのは、それなりの素質と力量があってこそです。次に目指すべきは、扱いやすいコードのスタイルを身につけることでしょうか笑。クラスや構造体のような技術も含めて。
houki

2018/08/16 15:13

この一連の内容を真摯に受け止めて、精進していきます。ありがとうございました。 綺麗なコードをかけるように、頑張ります!
yumetodo

2018/08/16 15:16

手のひらを返すようになってしまいますが、汚いけど必要な機能があるプログラムときれいだけど必要な機能がないプログラムなら前者のほうがいいということをお忘れなく。まあ汚く書いたツケは確実にあとで襲いかかってきますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問