递归函数中的分段错误。使用std :: stack(C ++)

时间:2013-01-05 22:22:56

标签: c++ recursion stl stack segmentation-fault

为什么我会遇到分段错误以及如何修复它?

我正在编写下面的代码,通过迷宫递归“遍历”并找到路径的总数。我正在使用堆栈来跟踪“下一步”。

ROWS和COLUMNS定义迷宫的大小。如果我将这些参数设置为大于9x9,则会出现分段错误。我不知道为什么我会这样做。

这是我第一次使用gdb并获得以下内容:

#3  0x0000000000400de0 in std::stack<xy, std::deque<xy, std::allocator<xy> > >::top (this=0x604400 <buff>)
at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_stack.h:161
161     return c.back();

让我相信它与我的筹码有关。

我感谢任何帮助。感谢。

守则:

#define ROWS 10
#define COLUMNS 10

#include<iostream>
#include<stack>
using namespace std;

struct xy
{
  long i;
  long j;
};

stack<xy> buff;

long goRight (long j)
{
  if (j < COLUMNS-1)
    return 1;
  else
    return 0;
}

long goDown (long i)
{
  if (i < ROWS-1)
    return 1;  
  else
    return 0;
}

long traverse (xy POS)
{
  long fD = goDown(POS.i);
  long fR = goRight(POS.j);

  xy toAdd;

  if (fD == 1)
    {
      toAdd.i=POS.i+1;
      toAdd.j=POS.j;
      buff.push(toAdd);
    }

  if (fR == 1)
    {
      toAdd.i=POS.i;
      toAdd.j=POS.j+1;
      buff.push(toAdd);
    }

  if(buff.empty())
    return 0;

  toAdd = buff.top();
  buff.pop();

  return (traverse(toAdd) + (fD * fR));
}

int main()
{
  xy initial;
  initial.i=0;
  initial.j=0;

  cout << 1 + traverse(initial);

  return 1;
}

2 个答案:

答案 0 :(得分:1)

您的call stack内存有限,您调用的每个函数都在该堆栈上使用内存。因此,通过一个巨大的迷宫递归强制将最终以 stack overflow 结束。使用gdb的backtrace函数应该清楚地显示出来。

您应该重新考虑算法并使用迭代而不是递归。 在您的情况下,您似乎想要实现某种flood fill algorithm,这很容易通过迭代来完成,如link中所述。

另请注意,如果您使用的是Linux系统,使用ulimit -s unlimited将允许您为从此终端仿真程序运行的所有程序使用call stack的无限量内存。那么你的程序不应该是段错误的。

祝你好运。

答案 1 :(得分:0)

我相信你不需要一个std::stack对象来实现你想要的(即计算路径数)。而且你不一定要切换到迭代,这使得这个算法更难写,只是简化了算法及其终止条件。

这是一个可能的解决方案(顺便说一下,如果你打算用行数和列数来更高,可以考虑切换到long long以避免整数 - 不是堆栈 - 溢出):

#define ROWS 10
#define COLUMNS 10

#include<iostream>
#include <stack>

using namespace std;

struct xy
{
  long i;
  long j;
};

stack<xy> partialPath;

long goRight (long j)
{
  if (j < COLUMNS - 1)
    return 1;
  else
    return 0;
}

long goDown (long i)
{
  if (i < ROWS - 1)
    return 1;
  else
    return 0;
}

long traverse (xy const& POS)
{
    partialPath.push(POS); // Not needed to count the # of paths, but if you want...

    long fD = goDown(POS.i);
    long fR = goRight(POS.j);

    xy nextPos;
    long numOfPaths = 0;
    if (fD == 1)
    {
        nextPos.i=POS.i+1;
        nextPos.j=POS.j;
        numOfPaths += traverse(nextPos);
    }

    if (fR == 1)
    {
        nextPos.i=POS.i;
        nextPos.j=POS.j+1;
        numOfPaths += traverse(nextPos);
    }

    partialPath.pop(); // Not needed to count the # of paths, but if you want...

    if ((fD == 0) && (fR == 0))
    {
        return 1;
    }

    return numOfPaths;
}

int main()
{
  xy initial;
  initial.i=0;
  initial.j=0;

  cout << traverse(initial);

  return 0;
}

P.S:为了进一步提高效率,最好通过const ref传递POS参数。另外,我认为用于指示您的流程成功的返回码应为0而不是1(我的意思是return main()语句中的。{/ p>