Каковы потенциальные последствия глубокого стека вызовов в Perl? - PullRequest
1 голос
/ 16 января 2010
  • Мне сказали, что следующая часть кода является глубоко рекурсивной. Однако я не понимаю, как - кто-то может объяснить?
  • Если так, каковы связанные с этим последствия?

Примечание:

Тривиальный пример

            check:
            # Grab some data held in a file
            while ((ReadFile ()) != 0 ) { 
                    if ((checkSomething ()) != 1) {
                            # value found, check file again
                            next check;
                    } else {
                            blah ($doo, $foo);
                    }
            }

Обновление:

  • Спасибо за исправление.
  • Каковы последствия следующего, с точки зрения потребления памяти - это не рекурсия, насколько я понимаю, и после рассмотрения других вопросов:

    sub D {
            ..
    }
    sub C {
            D ();
    }
    sub B {
            C ();
    }
    sub A {
            while (true) {
                    B ();
            }
    }
    

Ответы [ 4 ]

8 голосов
/ 16 января 2010

Ваш второй пример также не является примером рекурсии. Это всего лишь пример того, что я бы неофициально назвал «связанными вызовами подпрограмм» - я не верю, что есть формальный термин для этого. Рекурсия требует, чтобы подпрограмма вызывала сама себя либо напрямую, либо через некоторый набор посредников.

Например, если подпрограмма D имеет вызов A, B или C при определенных условиях, это будет рекурсия.

Что касается глубоких стеков вызовов, ответ зависит от:

  • как глубоко
  • сколько аргументов вы передаете в каждом
  • сколько памяти может выделить ваша программа

Каждый раз, когда вы вызываете подпрограмму, она добавляет новый кадр в стек вызовов. Этот кадр остается до завершения подпрограммы. Размер этого стекового фрейма зависит в первую очередь от длины вашего списка аргументов плюс некоторые фиксированные накладные расходы.

Так что в этом случае у вас будет стековый фрейм с четырьмя элементами.

Если ваша цепочка вызовов становится слишком глубокой и каждая запись имеет длинный список аргументов, вам в конечном итоге не хватит места для стека вызовов. Это называется переполнением стека. :)

4 голосов
/ 16 января 2010

Как уже говорили другие, ваш код не рекурсивный, так что не беспокойтесь об этом. Однако, это будет чище и проще для чтения, если вы удалите ненужную ветку if, сделав условие для ветви else единственной, и сбросив метку icky:

while ((ReadFile ()) != 0 ) { 
    if ((checkSomething ()) == 1) {
        blah ($doo, $foo);
    }
}
3 голосов
/ 16 января 2010

В этом коде нет рекурсии.

Ваш код может иметь рекурсию, но он не показан в предложенном вами коде.

0 голосов
/ 16 января 2010

Я согласен с JS Bangs, но другой альтернативой ярлыку icky будет использование оператора continue вместо «следующей проверки». JS Bangs лучше всего подходит для этого кода, но операторы continue имеют свое место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...