実現したいこと
- 大きいサイズの迷路でもSegmentation faultが出ずに探索できるようにする。
前提
C言語でスタックを用いて迷路探索のプログラムを書こうとしています。
サイズの小さい迷路では問題なく動作することが確認できています。
また分岐に対応していない(1本道の迷路のみに使える)プログラムでは問題なく動作しています。
最初に迷路のサイズの上限を1024×1024と設定したのですが、それよりも小さい迷路であってもSegmentation faultが出てしまいます。入力となる迷路データは別にtxt形式で保存し実行の際に読み込ませています。メインのソースコードのファイル名がq3-5.cであり読み込ませる迷路データのファイル名がq3-mazeex5.txtとしています。
発生している問題・エラーメッセージ
$ gcc -std=c99 -o q3-5 q3-5.c $ ./q3-5 < q3-mazeex5.txt $ Segmentation fault
該当のソースコード
c
1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5#define MAX_MAZE_SIZE 1024 6#define NUMBER_OF_DIRECTIONS 4 // left, right, up, down 7 8enum { FORWARD, BACKWARD }; 9typedef int bool; 10typedef struct { int i, j; } position; 11typedef struct { 12 int size_row, size_col; 13 char map [ MAX_MAZE_SIZE ][ MAX_MAZE_SIZE ]; 14 position start, goal; 15} maze; 16 17/////////////////////////////////////////////////////////////////////////////// 18// Stack definition 19/////////////////////////////////////////////////////////////////////////////// 20#define STACKSIZE MAX_MAZE_SIZE 21typedef position elementtype; 22 23typedef struct { 24 int top; 25 elementtype elements[STACKSIZE]; 26} stack; 27 28void initstack(stack *s) 29{ 30 s->top = -1; 31} 32 33int stackempty(stack *s) 34{ 35 return (s->top < 0); 36} 37 38void printstack(stack *s) 39{ 40 printf("["); 41 for(int i = 0; i <= s->top; i++){ 42 printf("(%d,%d)", s->elements[i].i, s->elements[i].j); 43 if (i < s->top) { 44 printf(", "); 45 } 46 } 47 printf("]\n"); 48} 49 50void push(stack *s, elementtype x, char c) 51{ 52 s->top += 1; 53 if (s->top >= STACKSIZE) { 54 printf("Stack overflow.\n"); exit(1); 55 } else { 56 s->elements[s->top] = x; 57 } 58 printf("%c push (%d,%d): ", c, x.i, x.j); 59 printstack(s); 60 return; 61} 62 63elementtype pop(stack *s, char c) 64{ 65 elementtype x; 66 if (s->top < 0){ 67 printf("%c Stack is empty.\n", c); exit(1); 68 } else { 69 x = s->elements[s->top]; 70 s->top -= 1; 71 printf("%c pop: (%d,%d), ", c, x.i, x.j); 72 printstack(s); 73 return x; 74 } 75} 76/////////////////////////////////////////////////////////////////////////////// 77 78position possible_moves [ 4 ] = { 79 { .i = 0, .j = -1 }, 80 { .i = 0, .j = +1 }, 81 { .i = -1, .j = 0 }, 82 { .i = +1, .j = 0 } }; 83position move ( position p, position d ) { position q = { .i = p.i + d.i, .j = p.j + d.j }; return q; } 84bool equal ( position p, position q ) { return ( p.i == q.i && p.j == q.j ) ? 1 : 0; } 85 86void read_maze ( maze *m ) 87{ 88 char str [ MAX_MAZE_SIZE + 2 ]; // +2 = '\n' + '\0' 89 position p = { .i = 0, .j = 0 }; 90 91 while ( fgets ( str, MAX_MAZE_SIZE + 2, stdin ) ) { 92 for (p.j = 0; str [ p.j ] != '\n'; p.j++ ) { 93 m->map [ p.i ][ p.j ] = str [ p.j ]; 94 if ( str [ p.j ] == 'S' ) { 95 m->start = p; 96 } 97 if ( str [ p.j ] == 'G' ) { 98 m->goal = p; 99 } 100 } 101 p.i += 1; 102 } 103 m->size_row = p.i; 104 m->size_col = p.j; 105} 106 107void print_maze ( maze m ) 108{ 109 position a; 110 111 printf(" "); 112 for ( int j = 0; j < m.size_col; j++ ) { 113 printf("%d", j%10); 114 } 115 printf("\n"); 116 117 for ( a.i = 0; a.i < m.size_row; a.i++ ) { 118 printf("%d", a.i%10); 119 for ( a.j = 0; a.j < m.size_col; a.j++ ) { 120 printf ( "%c", m.map [ a.i ][ a.j ] ); 121 } 122 printf ( "\n" ); 123 } 124} 125 126bool is_in ( maze *m, position p ) { return ( 0 <= p.i && p.i <= m->size_row - 1 && 0 <= p.j && p.j <= m->size_col - 1 ) ? 1 : 0; } 127bool is_goal ( maze *m, position p ) { return ( m->map [ p.i ][ p.j ] == 'G' ) ? 1 : 0; } 128bool is_wall ( maze *m, position p ) { return ( m->map [ p.i ][ p.j ] == '#' ) ? 1 : 0; } 129int next_possible_move ( maze *m, position cur, position prev, position candidate [] ) 130{ 131 int n = 0; 132 for ( int i = 0; i < NUMBER_OF_DIRECTIONS; i++ ) { 133 position next = move ( cur, possible_moves [ i ] ); 134 if ( is_in ( m, next ) && ! is_wall ( m, next ) && ! equal ( next, prev ) ) { candidate[n] = next; n += 1; } 135 } 136 return n; 137} 138 139void solve ( maze *m ) 140{ 141 position start = m->start; 142 position goal = m->goal; 143 stack route, branch; 144 position cur, next, prev; 145 position candidate [ NUMBER_OF_DIRECTIONS ]; // left, right, up, down; 146 bool direction = FORWARD; 147 148 initstack ( &route ); 149 initstack ( &branch ); 150 151 prev = start; 152 cur = start; 153 int n = next_possible_move ( m, cur, prev, candidate ); // 次の可能な移動を検索 154 push ( &route, cur, 'r' ); 155 cur = candidate [ 0 ]; 156 157 printf("START\n"); 158 while(! is_goal ( m, cur ) ) { // ゴールに到達するまで繰り返し 159 printf("CUR: (%d,%d)\n", cur.i, cur.j); 160 n = next_possible_move ( m, cur, prev, candidate ); // 次の可能な移動を検索 161 prev = cur; 162 switch ( n ) { 163 164case 0: // 行き止まり 165 if (stackempty(&branch)) 166 { 167 printf("No solution found.\n"); 168 return; 169 } 170 direction = BACKWARD; 171 cur = pop(&route, 'r'); // 逆戻り 172 printf("%s\n", (direction == FORWARD) ? "FORWARD" : "BACKWARD"); 173 break; 174 175 case 1: // 一本道 176 if (direction == FORWARD) 177 { 178 push(&route, cur, 'r'); 179 cur = candidate[0]; 180 } 181 else 182 { 183 cur = pop(&route, 'r'); 184 } 185 printf("%s\n", (direction == FORWARD) ? "FORWARD" : "BACKWARD"); 186 break; 187 188 default: // 分岐 189 printf("BRANCH\n"); 190 if(direction == FORWARD){ 191 push(&route, cur, 'r'); 192 for (int i = 0; i < n; i++){ 193 next = candidate[i]; 194 if(!is_wall(m, next)){ 195 push(&branch, next, 'b'); 196 } 197 } 198 cur = pop(&branch, 'b'); 199 } 200 else{ 201 cur = pop(&branch, 'b'); 202 direction = FORWARD; 203 } 204 205 printf("%s\n", (direction == FORWARD) ? "FORWARD" : "BACKWARD"); 206 break; 207 } 208 } 209 210 211 // ゴールに到達した 212 // 行儀悪いけど、構造体の内容を書き換えて経路を追加 213 printf("DONE\n"); 214 while ( 1 ) { 215 cur = pop ( &route, 'r' ); 216 if ( equal ( cur, start ) ) { break; } 217 m->map [ cur.i ][ cur.j ] = '.'; 218 } 219 220} 221 222int main(void) 223{ 224 maze m; 225 226 read_maze ( &m ); 227 228 solve ( &m ); 229 230 print_maze ( m ); 231 232 return 0; 233}
txt
1############################# 2##############S############## 3############## ############## 4####### ###### ###### ####### 5###### ###### 6####### ###### ###### ####### 7############## ############## 8####### ###### ###### ####### 9#### ### ### #### 10####### ###### ###### ####### 11####### ###### ###### ####### 12#### ### ### #### 13####### ###### ###### ####### 14####### ###### ###### ####### 15####### ###### ###### ####### 16# # 17####### ###### ###### ####### 18####### ###### ###### ####### 19####### ###### ###### ####### 20#### ### ### G #### 21####### ###### ###### ####### 22####### ###### ###### ####### 23#### ### ### #### 24####### ###### ###### ####### 25############## ############## 26####### ###### ###### ####### 27###### ###### 28####### ###### ###### ####### 29#############################
試したこと
gdbを用いてデバッグしたところ、上のソースコードの93行目に問題があると表示されました。
しかしこの部分のどこに問題があるのかわかりません。
補足情報(FW/ツールのバージョンなど)
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0