Perl中深度调用堆栈的潜在影响是什么?

时间:2010-01-15 23:33:18

标签: perl

  • 我被告知以下部分代码是深度递归的。但是我不明白 - 有人可以解释一下吗?
  • 如果是,那么相关的含义是什么?

注意:

琐碎的例子

            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 个答案:

答案 0 :(得分:8)

你的第二个例子也不是递归的例子。这只是我非正式地称之为“链式子程序调用”的一个例子 - 我不相信它有一个正式的术语。递归要求子程序直接或通过一组中介来调用自身。

例如,如果子程序D在某些条件下调用了A,B或C,那就是递归。

至于深度调用堆栈,答案取决于:

  • 有多深
  • 你在每个中传递了多少个参数
  • 您的程序可以分配多少内存

每次调用子例程时,它都会在调用堆栈上添加一个新帧。该子帧一直保持到子程序完成为止。此堆栈帧的大小主要取决于参数列表的长度,加上一些固定的开销。

所以在这种情况下,你有一个包含四个元素的堆栈框架。

如果您的调用链变得太深并且每个条目都有很长的参数列表,那么最终您的调用堆栈空间将耗尽。这称为堆栈溢出。 :)

答案 1 :(得分:4)

正如其他人所说,你的代码不是递归的,所以不要担心。但是,如果通过使if分支的条件成为唯一的条件来消除无用的else分支,那么它将更清晰,更容易阅读,并删除icky标签:

while ((ReadFile ()) != 0 ) { 
    if ((checkSomething ()) == 1) {
        blah ($doo, $foo);
    }
}

答案 2 :(得分:3)

该代码中没有递归。

您的代码可能有递归,但它没有显示在您提供的代码中。

答案 3 :(得分:0)

我同意JS Bangs,但是另一个替代icky标签的方法是使用continue语句而不是“next check”。 JS Bangs是这个代码的最佳选择,但是继续声明取而代之。