PHP在特定数量的递归循环后停止执行


PHP stops executing after specific amount of recursion loops

我遇到的问题很奇怪。它发生在做递归循环的时候。当使用for循环或任何其他迭代执行相同的任务时,不会发生这种情况。

当递归调用一个函数低于~ 21000次时,一切都正常。

当超过此数值时,会出现问题。

工作代码:

foo();
function foo($i = 1) {
    if ($i > 20000) {
         return;
    }
    echo $i . '<br/>';
    foo($i + 1);
    return;        
}

输出:

19998
19999
20000

不工作的代码:

foo();
function foo($i = 1) {
    if ($i > 30000) {  // Or any number above ~21000
         return;
    }
    echo $i . '<br/>';
    foo($i + 1);
    return;        
}

输出:

13493
13494
13

最后一行停在号码中间。在某些情况下,它只向服务器发送一个空响应。

我在Ubuntu上使用apache2服务器,PHP版本5.6.10。使用Xampp,也会出现同样的问题,只是数字有点不同。

在包括PHP在内的大多数当前流行的编程语言中,函数可以执行多少递归都是有限制的。这不是一个硬性限制;根据程序的状态,它可以是数万个深度的递归调用,也可以是几个深度的递归调用。因此,像您的示例那样实现深度递归函数是不安全的,并且您的程序将崩溃。请参阅PHP用户定义函数文档底部的注释:

超过100-200个递归级别的递归函数/方法调用可能会破坏堆栈并导致当前脚本终止。

每次调用函数时,程序必须在开始执行函数之前记录执行位置,以便在函数返回后知道从哪里开始再次执行。存储这些信息的空间是有限的,所以如果同时有太多的函数调用,就会耗尽空间,程序就会崩溃。这个信息,连同一堆其他信息,被存储在堆栈中,当你用完堆栈中的空间时,它被称为堆栈溢出或粉碎堆栈。

一些语言实现了一个被称为尾部调用优化的特性,它允许在适当的情况下无限递归。函数式语言通常支持这一点,如Scheme和ML。然而,PHP不支持,如PHP是否优化尾部递归?