2016-08-18 6 views
-1

私は次の機能を実装しようとしています。 は次のとおりです。私はこのコードブロックがセグメンテーションフォールトを与える理由を理解できません

  1. は座標をとります。
  2. は、周囲のセルに重みを割り当てます。
  3. は、これらの重みとセルの方向をマップに格納します。
  4. は地図をループします。最も低い体重から開始する。
  5. 呼び出しは、隣接セル座標で再び移動します。

コードスニペット:

120 void move(const int x, const int y) 
121 { 
122   map<int, int> nextDir; 
123   map<int, int>::iterator it; 
124   if((x == maxX - 1) && (y == maxY - 1)) 
125   { 
126     int groundCopy[maxX][maxY]; 
127     memcpy(((void *)&groundCopy), ((void *)&ground), sizeof(groundCopy)); 
128     traceBack(x, y); 
129     memcpy(((void *)&ground), ((void *)&groundCopy), sizeof(ground)); 
130     printPPM(); 
131   } 
132   for(int i = 0; i < 8; ++i) 
133   { 
134     if(!isValid(x + dirX[i], y + dirY[i])) 
135       continue; 
136     int temp = weight[x][y][0] + ground[x + dirX[i]][y + dirY[i]] + disWeight(x, y, x + dirX[i], y + dirY[i]); 
137     if(!(weight[x + dirX[i]][y + dirY[i]][0] == numeric_limits<int>::max())) 
138       temp += weight[x + dirX[i]][y + dirY[i]][0]; 
139     if(temp < weight[x + dirX[i]][y + dirY[i]][0]) 
140     { 
141       weight[x + dirX[i]][y + dirY[i]][0] = temp; 
142       weight[x + dirX[i]][y + dirY[i]][1] = 7 - i; 
143       nextDir[temp] = i; 
144     } 
145     else 
146       continue; 
147   } 
148   for(it = nextDir.begin(); it != nextDir.end(); ++it) 
149     move(x + dirX[it->second], y + dirY[it->second]); 
150 } 

バックトレース情報:

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000401760 in move (x=<error reading variable: Cannot access memory at address 0x7fffff5ab18c>, y=<error reading variable: Cannot access memory at address 0x7fffff5ab188>) at codes/terrainExample.cpp:121 
121 { 
(gdb) bt 
#0 0x0000000000401760 in move (x=<error reading variable: Cannot access memory at address 0x7fffff5ab18c>, y=<error reading variable: Cannot access memory at address 0x7fffff5ab188>) at codes/terrainExample.cpp:121 
#1 0x0000000000401bfa in move (x=0, y=1) at codes/terrainExample.cpp:149 
#2 0x0000000000401bfa in move (x=0, y=0) at codes/terrainExample.cpp:149 
#3 0x0000000000401dbb in solve() at codes/terrainExample.cpp:167 
#4 0x0000000000401f1c in main() at codes/terrainExample.cpp:186 

私の実装の何が問題になっているのですか?必要な場合は、次の

は、コードとvalgrindのログへのリンクです: このコードでhttps://www.dropbox.com/s/5m8zfxubq6lcl8o/terrainExample.cpp?dl=0 https://www.dropbox.com/s/wq7ob1uevwutsov/logfile.out?dl=0

私が代わりにマップのベクトルを使用しています。

+1

デバッガでコードをステップ実行するときにインデックス変数を確認し、境界内で配列にアクセスするようにしてください。 –

+0

行134私はそれをやっています。 bool isValid(const int x、const int y){if((x <0)||(y <0) || (x> = maxX)||(y> = maxY))はfalseを返します。 return true;}デバッグ時に もチェックしました。 – prad

答えて

1

これは興味深いコードですが、私は本当に面白そうでした。だからそれを解剖しましょう。

まず、valgrindのはそれは、文句を言う:これは私に語っ

==15718== Warning: client switching stacks? SP change: 0xfff000420 --> 0xffed6b8d8

どこかにスタックスマッシングであります。コードを拾い読みした後、実際にどちらか、そこにスタックに保存されている巨大なローカル変数は、そう:

  1. 画像のサイズを小さくしようとする(例えば const int maxX = 320; const int maxY = 640;修正スタックの問題を設定)
  2. しかし、本当に大きな画像サイズが必要な場合は、単に動的メモリ管理を行います。

ただし、アプリケーションがまだどこかでクラッシュ...と私は再帰で何度もnextMoveを呼び出して...よく、再びスタックを乱すことがわかります。 void nextMove(int x, int y)からvoid nextMove(const int x, const int y)から

  1. 変更nextMove:だから、物事をより良くするために、このような何かを行います。私はパラメータの定数を削除したばかりですが、分かります。代わりに、最後nextMove(nx, ny);で再帰関数を呼び出すの

  2. ような何かを:

    void nextMove(int x, int y) { again:

    と最後ではなく、少なくとも:

  3. はちょうど関数の先頭で、ラベルを追加します: x = nx; y = ny; goto again;

を使用してだから私はそれらにgotoを持っていない答えを提供するように彼らに依頼します。

希望すると便利です。

+0

ありがとう@fritzone、それは働いた。私はすべての大きな配列を動的に割り当てられるように変更しました。プリセットされたnextMove呼び出しのxとyの値が変更されたので、gotoは使用しませんでした。 – prad

関連する問題