Ошибка переполнения стека в функции цикла - PullRequest
3 голосов
/ 07 февраля 2012

Я довольно новичок в 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
}

Ответы [ 8 ]

1 голос
/ 07 февраля 2012

Точки выхода нет, поэтому переполнение стека. Вам необходимо создать условие для рекурсивного вызова, иначе он никогда не сможет выйти.

Пример:

    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(); 
        }

    }
1 голос
/ 07 февраля 2012

Вы правы. У вас есть рекурсивная функция, у которой нет подходящего условия остановки. Может быть, вам нужен цикл, который идет от 1 до 100000, и там вы вызываете функцию loadFoving (). Переполнение стека вызвано тем, что вы вызываете loadFoving () бесконечное количество раз, в конце концов вам не хватает места в стеке.

, например

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

    }
0 голосов
/ 07 февраля 2012

Проблема в том, что всякий раз, когда вы вызываете функцию в c ++, она занимает некоторую память (помимо прочего, для хранения своих переменных требуется место).Эта память называется стековым фреймом.Память автоматически возвращается, когда функция возвращается, но если у вас есть рекурсивная функция, ни один из стековых фреймов не может быть освобожден, пока не произойдет финальный вызов функции.В этом случае LoadFoving пытается бесконечно вызывать себя, а ваш компьютер не содержит бесконечного объема памяти.

В 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);
        }
    }
}

В качестве альтернативы вы можете переместить вызов LoadFabilities в оператор if, чтобы не пытаться вызывать LoadFoving бесконечное число раз.Это может сработать, но в зависимости от того, сколько раз вы вызываете LoadFoving, вы все равно можете столкнуться с той же ошибкой.Эту ошибку можно избежать с помощью правильной оптимизации компилятора, но, как правило, здесь безопаснее и понятнее просто использовать цикл.

0 голосов
/ 07 февраля 2012

Вы должны делать это в цикле, не используя рекурсию.Каждый раз, когда вы повторяете это, он будет добавлять информацию в стек, и в конечном итоге вам не хватит места в стеке.В этом случае вы повторяетесь бесконечно.(Вы не помешаете ему повторяться, если число> 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;
    }
}

( edit : дополнительный комментарий об "" "+ number +" '"удален)

0 голосов
/ 07 февраля 2012
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» отбрасывается, а не пытается вернуться).

Причина изменения заключается в том, что вы хотите продолжить, только если число

0 голосов
/ 07 февраля 2012

проблема в том, что при числе> 100001 ваш код все еще работает (увеличивается на 1 каждый раз и не выходит из цикла). поэтому измените код на это:

 if (number <= maxnumber)
            {
                if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'"))
                {
                    this.listBox1.Items.Add(number);
                }
                number = number + 1;
                LoadFavorites();
            }
0 голосов
/ 07 февраля 2012

Вы вызываете LoadFoving рекурсивно без каких-либо правил для завершения рекурсии.Просто поместите это в себя, если заявление ... Но почему бы вам не написать это так:

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);
        }
    }
}
0 голосов
/ 07 февраля 2012

Вы хотите переместить деталь, увеличивающую число, внутрь оператора 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
        }
    }
...