【问题标题】:PHP stops executing after specific amount of recursion loopsPHP 在特定数量的递归循环后停止执行
【发布时间】:2015-07-16 00:10:51
【问题描述】:

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

当递归调用一个函数低于约 21 000 次时,一切正常。执行此号码时出现问题。

我的工作代码:

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 上使用 PHP 版本 5.6.10 的 apache2 服务器。使用 Xampp 也会出现同样的问题,只是数字略有不同。

【问题讨论】:

  • 听起来像是内存问题。尝试更改您的最大内存设置,重新启动 Apache,然后再次运行您的代码。
  • 是否存在需要 30K 递归调用的真实场景?听起来简单的循环会在这里更有效地解决问题。
  • 每个脚本允许使用多少内存?我认为默认值为 128,因此您可能希望将其更改为 256,如果您认为需要,可能会更高。检查你的 PHP ini 是否有“memory_limit”
  • 增加 xdebug.max_nesting_level。在这里查看答案stackoverflow.com/questions/17488505/…
  • 执行时间呢?还是输出缓冲区?

标签: php recursion


【解决方案1】:

在大多数当前流行的编程语言中,包括 PHP,一个函数可以执行多少递归是有限制的。这不是硬性限制;根据您的程序的状态,它可以是数万深的递归调用或只有几深的递归调用。因此,像你的例子那样实现深度递归函数是不安全的,你的程序会崩溃。请参阅 PHP 的 user-defined functions 文档底部的注释:

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

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

某些语言实现了一种称为tail call optimization 的功能,它允许在适当的情况下无限递归。函数式语言通常支持这一点,例如 Scheme 和 ML。然而,PHP 没有,正如Does PHP optimize tail recursion? 中提到的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多