【问题标题】:Stack overflow error in loop function循环函数中的堆栈溢出错误
【发布时间】:2012-02-07 01:47:07
【问题描述】:

我对 c# 很陌生,我正在尝试创建一个函数来检查某个数字是否在列表中,并且我想为 1-10000 之间的每个数字运行该函数。 目前它看起来像这样,但我得到 System.StackOverflowException 所以有人知道如何正确执行此操作吗?

int number = 1; 
int maxnumber = 10000; 
void LoadFavorites()
{

    if (number <= maxnumber)
    {
        if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
        {
            this.listBox1.Items.Add(number);
        }
    }

    // Increases number by 1 and reruns
    number = number + 1;
    LoadFavorites(); // problem is probably here
}

【问题讨论】:

  • 你是在递归地做吗?这真的是你想要的吗?还是你只想使用一个简单的循环?

标签: c# stack-overflow


【解决方案1】:

你是对的。您在那里有一个没有适当停止条件的递归函数。也许您需要一个从 1 到 100000 的循环,然后调用函数 loadFavorites()。 stackoverflow 是因为你无限次调用 loadFavorites() 导致堆栈空间不足。

例如

    for(int i=number; i<maxNumber; i++)
    {
        if (Properties.Settings.Default.FavoriteList.Contains("'"+i+"'"))
            {
                this.listBox1.Items.Add(i);
            }

    }

【讨论】:

    【解决方案2】:

    没有退出点,因此堆栈溢出。 您需要在递归调用上创建一个条件,否则它将永远无法退出。

    例子:

        void LoadFavorites()
        {
    
            if (number <= maxnumber)
            {
                if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                {
                    this.listBox1.Items.Add(number);
                }
            }
    
            // Increases number by 1 and reruns
            number = number + 1;
    
            if(number <= maxnumber) // create a condition to call this
              LoadFavorites(); // problem is probably here
        }
    

    更好的方法

        void LoadFavorites()
        {
    
            if (number <= maxnumber)
            {
                if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                {
                    this.listBox1.Items.Add(number++); // add number to list THEN increment number by one 
                }
                LoadFavorites(); 
            }
    
        }
    

    【讨论】:

      【解决方案3】:

      您应该在循环中执行此操作,而不是使用递归。每次递归时,它都会将信息添加到堆栈中,最终您将耗尽堆栈空间。在这种情况下,您将无限递归。 (如果 number > maxnumber,您不会阻止它递归)。

      void LoadFavorites()
      {
          int number = 1; 
          int maxnumber = 10000; 
          while (number <= maxnumber)
          {
             if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
             {
                 this.listBox1.Items.Add(number);
             }
             number = number + 1;
          }
      }
      

      编辑:关于“'”+数字+“'”的附加评论已删除)

      【讨论】:

      • 非常感谢,我会用它来代替。虽然 "'"+number+"'" 是这样的,因为我也以这种方式制作了最喜欢的保存系统以避免它,例如认为在 23 号有一个最爱,而在 7236 上确实有一个或什么的
      • 嗯,好的,我会删除其余的信息。
      【解决方案4】:

      您想将增加数字的部分移动到if 语句内:

          int number = 1; 
          int maxnumber = 10000; 
          void LoadFavorites()
          {
      
              if (number <= maxnumber)
              {
                  if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                  {
                      this.listBox1.Items.Add(number);
                  }
      
                  // Increases number by 1 and reruns
                  number = number + 1;
                  LoadFavorites(); // problem is probably here
              }
          }
      

      【讨论】:

        【解决方案5】:

        您正在递归调用 LoadFavorites,而没有任何结束递归的规则。只是,把它放在你的 if 语句中......但是你为什么不这样写:

        int number = 1; 
        int maxnumber = 10000; 
        void LoadFavorites()
        {
            for(var i = number; i <= maxnumber; i++)
            {
                if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                {
                    this.listBox1.Items.Add(number);
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          问题是当数字>100001 时,您的代码仍在运行(每次递增 1 且不退出循环)。 所以把代码改成这样:

           if (number <= maxnumber)
                      {
                          if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                          {
                              this.listBox1.Items.Add(number);
                          }
                          number = number + 1;
                          LoadFavorites();
                      }
          

          【讨论】:

            【解决方案7】:
            int number = 1; 
            int maxnumber = 10000; 
            void LoadFavorites()
            {
            
                if (number <= maxnumber)
                {
                    if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                    {
                        this.listBox1.Items.Add(number);
                    }
                }
            
                // Increases number by 1 and reruns
                number = number + 1;
                LoadFavorites(); //**MOVE THESE:
            }
            

            改成

            int number = 1; 
            int maxnumber = 10000; 
            void LoadFavorites()
            {
            
                if (number <= maxnumber)
                {
                    if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                    {
                        this.listBox1.Items.Add(number);
                        // Increases number by 1 and reruns
                        number = number + 1;
                        LoadFavorites(); // problem is probably here
                    }
                }
            }
            

            您从函数内部调用函数,您可能知道,这就是递归。但是,使用递归,您必须有一个退出条件,这会导致循环退出。

            堆栈是线程中函数调用的顺序。例如,在 Java 中,您有 main() 这是您的入口点。从 main() 调用函数会添加到堆栈的顶部。一旦堆栈达到一定大小,您的计算机就不能再缓冲更多的函数调用。它只是从堆栈中删除主函数,并且不知道返回到哪里,所以它抛出了一个错误。 (一旦 'main' 被删除,它就会抛出错误,而不是一旦它试图返回)。

            更改的原因是您只想在 number 小于 maxnumber 时继续。这为递归设置了一个条件,之后,函数将退出。

            【讨论】:

              【解决方案8】:

              问题在于,每当您在 c++ 中调用函数时,它都会占用一些内存(它需要空间来存储其变量等)​​。该内存称为堆栈帧。函数返回时会自动返回内存,但如果您有递归函数,则在最终函数调用发生之前,不会释放任何堆栈帧。在这种情况下,LoadFavorites 会尝试无限地调用自己,而您的计算机不会包含无限量的内存。

              在 C++ 中,最好的答案通常是将其转换为循环 - 在这种情况下,您需要一个 for 循环。

              void LoadFavorites() {
                  int maxnumber = 10000;
                  int number;
                  for (number = 1; number <= maxnumber; number++) {
                      if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) {
                          this.listBox1.Items.Add(number);
                      }
                  }
              }
              

              或者,您可以将对 LoadFavorites 的调用移到 if 语句中,这样您就不会尝试无限次调用 LoadFavorites。这可能有效,但根据您调用 LoadFavorites 的次数,您仍然可能遇到相同的错误。通过正确的编译器优化可以避免该错误,但通常在这里简单地使用循环更安全、更清晰。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-12-15
                • 1970-01-01
                • 2018-07-10
                • 2017-12-15
                • 1970-01-01
                • 1970-01-01
                • 2017-09-05
                相关资源
                最近更新 更多