解决方案“致命错误:达到'100'的最大功能嵌套级别,正在中止!”用PHP

时间:2011-12-28 12:46:24

标签: recursion xdebug php

我创建了一个查找html文件中所有URL的函数,并为链接到发现的URL的每个html内容重复相同的过程。该函数是递归的,可以无休止地继续。但是,我通过设置一个全局变量来限制递归,这导致递归在100次递归后停止。

但是,php会返回此错误:

  

致命错误:达到最大功能嵌套级别'100',   中止!在   D:\ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php上线   1355

ERROR

我在这里找到了一个解决方案:Increasing nesting function calls limit但这不符合我的情况。

我引用了上述链接中的一个答案。请考虑一下。

  

“您是否安装了Zend,IonCube或xDebug?如果是这样,那可能是您收到此错误的地方。

     几年前我遇到过这个问题,结果是Zend把那个限制放在那里,而不是PHP。当然,删除它会让你超过100次迭代,但最终会达到内存限制。“

有没有办法在PHP中增加最大函数嵌套级别

22 个答案:

答案 0 :(得分:136)

增加php.ini

xdebug.max_nesting_level的值

答案 1 :(得分:54)

一个简单的解决方案解决了我的问题。我刚评论过这一行:

zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll

在我的php.ini文件中。此扩展将堆栈限制为100,因此我禁用了它。递归函数现在正如预期的那样工作。

答案 2 :(得分:44)

不是进行递归函数调用,而是使用队列模型来展平结构。

$queue = array('http://example.com/first/url');
while (count($queue)) {
    $url = array_shift($queue);

    $queue = array_merge($queue, find_urls($url));
}

function find_urls($url)
{
    $urls = array();

    // Some logic filling the variable

    return $urls;
}

有不同的方法来处理它。如果您需要了解所遍历的原点或路径,您可以跟踪更多信息。还有一些分布式队列可以使用类似的模型。

答案 3 :(得分:40)

另一个解决方案是在php.ini

中添加xdebug.max_nesting_level = 200

答案 4 :(得分:23)

您可以设置上限,例如

,而不是禁用xdebug
  

xdebug.max_nesting_level = 500

答案 5 :(得分:17)

也可以直接在php中修复此问题,例如在项目的配置文件中。

ini_set('xdebug.max_nesting_level', 200);

答案 6 :(得分:12)

可能是因为xdebug而发生的。

尝试在“php.ini”中评论以下行,然后重新启动服务器以重新加载PHP。

";xdebug.max_nesting_level"

答案 7 :(得分:12)

尝试查看/etc/php5/conf.d/以查看是否有名为xdebug.ini的文件

max_nesting_level默认为100

如果未在该文件中设置,请添加:

xdebug.max_nesting_level=300

到列表的末尾,所以它看起来像这个

xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300

然后,您可以在进行此更改之前和之后使用@Andrey's测试,看看是否有效。

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

答案 8 :(得分:12)

在Ubuntu上使用PHP 5.59:
得到了`:

  

/etc/php5/cli/conf.d

在该目录中找到 xdebug.ini ,在我的情况下是 20-xdebug.ini

并添加此行`

  

xdebug.max_nesting_level = 200


或者

  

xdebug.max_nesting_level = -1

将其设置为-1,您不必担心更改嵌套级别的值。

`

答案 9 :(得分:7)

的php.ini:

  

xdebug.max_nesting_level = -1

我不完全确定该值是否会溢出并达到-1,但它永远不会达到-1,或者它会将max_nesting_level设置得相当高。

答案 10 :(得分:6)

您可以将递归代码转换为迭代代码,模拟递归。这意味着当您到达链接时,必须将当前状态(网址,文档,文档中的位置等)推送到数组中,并在此链接完成时将其从数组中弹出。

答案 11 :(得分:6)

您可以尝试通过实现并行工作(例如在集群计算中)来摆动嵌套,而不是增加嵌套函数调用的数量。

例如:您定义有限数量的插槽(例如100)并监控分配给每个/部分插槽的“工作人员”的数量。如果任何插槽空闲,您可以将等待的工作人员“放入其中”。

答案 12 :(得分:5)

从命令行检查递归:

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

如果结果> 100然后检查内存限制;

答案 13 :(得分:3)

如果您正在使用Laravel,请执行

composer update

这应该可行。

答案 14 :(得分:2)

在开发过程中也偶然发现了这个错误。

但是,在我的情况下,它是由相互调用的函数的底层循环引起的 - 作为开发过程中不断迭代的结果。

供搜索引擎将来参考 - 我的日志提供给我的确切错误是:

Exception: Maximum function nesting level of '256' reached, aborting!

如果与我的情况一样,给定的答案不能解决您的问题,请确保您没有意外地按照以下简化情况执行某些操作:

function foo(){
    // Do something
    bar();
}

function bar(){
    // Do something else
    foo();
}

在这种情况下,即使您设置了 ini_set('xdebug.max_nesting_level', 9999);,它仍会在您的日志中打印出相同的错误消息。

答案 15 :(得分:2)

<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

P.S。将9999更改为您想要的任何数字。

答案 16 :(得分:0)

我在安装许多插件时出错了所以错误100显示包含我安装的最后一个插件的位置C:\ wamp \ www \ mysite \ wp-content \ plugins \“...”所以我删除C:驱动器上的这个插件文件夹,然后一切都恢复正常。我想我必须限制我安装或已激活插件的数量。运气好我希望它有所帮助

答案 17 :(得分:0)

我在cloud9上遇到了WordPress的这个问题。原来它是W3 Caching插件。我禁用了该插件,它工作正常。

答案 18 :(得分:0)

如果您在CLI(cmd)

中运行php脚本,则为另一种解决方案

在这种情况下,需要编辑的php.ini文件是不同的。在我的WAMP安装中,在命令行中加载的php.ini文件是:

\wamp\bin\php\php5.5.12\php.ini

而不是从浏览器运行php时加载的\ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini

答案 19 :(得分:0)

在你的情况下,它肯定是爬虫实例有更多的Xdebug限制来跟踪错误和调试信息。

但是,在其他情况下,像PHP或像CodeIgniter库这样的核心文件的错误也会产生这样的情况,如果你甚至增加x-debug级别设置,它就不会消失。

因此,请仔细查看您的代码:)。

以下是我的问题。

我有一个服务类,它是CodeIgniter中的库。像这样有一个函数。

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

  public function process(){
   //lots of Ci referencing here...
   }

我的控制器如下:

$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead  it shoud be like 

由于拼写错误,最后一行的函数调用是错误的,而应该如下所示:

$this->Payment_service->process(); //the library class name

然后我一直收到超出错误的消息。但我禁用了XDebug但没有帮助。无论如何,请检查您的班级名称或代码,以便正确调用函数。

答案 20 :(得分:0)

我遇到了同样的问题,我很喜欢这样:

打开MySQL my.ini文件

在[mysqld]部分中,添加以下行:innodb_force_recovery = 1

保存文件,然后尝试启动MySQL

删除刚刚添加的那一行并保存

答案 21 :(得分:0)

您还可以修改modifier.debug_print_var.php中的{debug}函数,以限制其递归到对象中。

第45行,之前:

$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);

之后:

$max_depth = 10;
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));

这样,Xdebug仍然会正常运行:限制var_dump中的递归深度,依此类推。 因为这是一个聪明的问题,而不是Xdebug!