我无法理解为什么这段代码会导致分段错误

时间:2016-08-18 08:55:00

标签: c++ iterator

我正在尝试实现以下功能。 它的作用是:

  1. 采用坐标。
  2. 为周围的细胞分配重量。
  3. 将这些权重和单元格方向存储在地图中。
  4. 循环遍历地图。从最低的重量开始。
  5. 使用相邻单元格坐标再次调用。
  6. 代码段:

    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

    在这段代码中我使用的是vector而不是map。

1 个答案:

答案 0 :(得分:1)

这是一段有趣的代码,看着它真的很有趣。所以让我们剖析它。

首先,valgrind抱怨说:

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

这告诉我那里有一堆粉碎在某个地方。在浏览代码之后,确实存在堆栈上存储的巨大局部变量,所以:

  1. 尝试缩小图像的大小(例如设置 const int maxX = 320; const int maxY = 640;解决了堆栈问题)
  2. 但如果你真的需要大图像尺寸,只需进行动态内存管理。
  3. 然而,应用程序仍然在某处崩溃......我发现在递归中反复调用nextMove ......好吧,再次扰乱堆栈。所以,为了让事情变得更好,做一些这样的事情:

    1. nextMovevoid nextMove(const int x, const int y)更改为void nextMove(int x, int y)。我刚刚删除了参数的常量,你会在一分钟内看到原因。
    2. 在函数的开头添加一个标签:

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

      最后但并非最不重要:

    3. 不要在末尾nextMove(nx, ny);递归调用函数,而是执行以下操作:x = nx; y = ny; goto again;

    4. 有些人会因为使用goto而讨厌我,所以我会要求他们提供一个没有goto个问题的答案。

      希望这有帮助!