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


137

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

但是,php返回此错误:

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

错误

我在这里找到了一个解决方案:增加嵌套函数的调用限制,但这在我的情况下不起作用。

我引用了上面提到的链接的答案之一。请考虑一下。

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

几年前,我碰到了这个问题,最后是Zend将该限制放在这里,而不是PHP。当然,删除它会让您超过100次迭代,但最终将达到内存限制。”

有没有一种方法可以提高PHP中的最大函数嵌套级别


2
另外:PHP对嵌套函数调用没有限制,它必须是您正在使用的扩展名,因此会导致这种情况。
亚伯

@Abel我确定我的代码没有错误。有一个静态变量,它在每次递归调用时将其值增加一。如果该变量小于100,则递归调用将继续进行直到变量达到100。我的意思是说达到100的变量实际上是基本情况。虽然错误发生在100次递归之前。正如您所提到的,某些扩展名是造成此问题的原因,我想提到的是,我使用的是来自simple_html_dom.php的函数。如果您对simple_html_dom.php有任何想法,请在这方面帮助我。请参考更新的问题。
拉斐

7
这是xdebug的错误。从屏幕快照中可以看到您正在使用xdebug。您可以在此处禁用设置:xdebug.max_nesting_level或确定嵌套级别的大小。
hakre 2012年

3
如果使用WAMP,请注意在php.ini中禁用xdebug并不总是有效;这同样适用于允许嵌套的扩展级别;一个错误的猜测;解决方案:转到php.ini并注释掉
php_xdebug

Answers:


145

增加的价值xdebug.max_nesting_level在你的php.ini


6
@AL您编辑php.ini文件,然后在XDebug部分中添加或编辑xdebug.max_nesting_level行。
Maxence

3
但是,如果这是生产环境,请参见接受的答案,即在该环境中禁用xdebug。
zkent

3
这可以解决症状(一段时间),但不能解决问题。
塞巴斯蒂安·马赫

1
当我在MAMP上使用UFront for Haxe时,此解决方案对我有用。
知己

4
无限:xdebug.max_nesting_level = -1
Nabi KAZ

55

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

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

在我的php.ini档案中。此扩展将堆栈限制为限制,100因此我将其禁用。递归功能现在正在按预期方式工作。


4
因此,最终它毕竟是XDebug扩展。如果愿意,您可以在两天内接受自己的答案作为接受的答案(并查看以前的问题,大多数人会错过接受的答案)。
亚伯

61
处理过度的递归肯定比仅关闭监视要好。
petesiss

7
这是一种笨拙的方法。上面提到的用于调整最大堆栈深度的变量的答案是一种更好的方法。
aredridel

7
您认为在生产环境中未启用xdebug。
HarryFink

2
哇靠。我无法停止对所选解决方案的嘲笑。因此,我的PC不会停止发出噪音,因此我找到了解决方案。把它关掉。:)
凯文·雷米索斯基

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;
}

有不同的处理方法。如果您需要有关原点或所经过路径的一些信息,则可以跟踪更多信息。也有可以处理类似模型的分布式队列。


5
使用SPL,您无需重新创建队列:php.net/manual/en/class.splqueue.php
Francesco

1
SPL Queue可能会提供更高的速度,但是我喜欢坚持执行大多数简单任务的阵列。都提供推/弹出/移位/取消移位。
路易·菲利普·胡伯多2011年

1
这是正确的答案。避免更改默认值。尝试优化您的代码。
Junaid Atique

41

另一个解决方案是xdebug.max_nesting_level = 200在您的php.ini中添加


8
也可以在php中进行,例如在项目的配置文件中。ini_set('xdebug.max_nesting_level', 200);
svassr 2014年

@htxryan我不是专家,但这是由于您的调用堆栈太“深”(调用其他函数的函数太多)。发生这种情况的典型情况是使用递归函数。该设置最有可能避免由于代码中的错误而导致“失控”递归。
布赖恩

@svassr,您可能要考虑将提示添加为单独的答案,或者添加到现有的提示中,这对我很有帮助,但在评论中几乎错过了它
Bryan 2015年

@Bryan刚刚添加了一个答案
svassr

23

您可以设置更高的限制,而不是禁用xdebug

xdebug.max_nesting_level = 500


@SebastianMach:而且,令人惊讶的是,几年之后。:)(大概再四次。人们不仅现在不阅读,甚至都不滚动。)
Sz。

1
@Sz .:哇,过去的爆炸声:P令人震惊。
塞巴斯蒂安·马赫

18

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

ini_set('xdebug.max_nesting_level', 200);


1
谢谢,这很好用,因为我不必担心在我所有的开发箱上更新php.ini,我只是将其添加到应用程序的引导文件中。
布赖恩

13

进入您的php.ini配置文件并更改以下行:

xdebug.max_nesting_level=100

像这样:

xdebug.max_nesting_level=200

13

在使用PHP 5.59的Ubuntu上:
到`:

/etc/php5/cli/conf.d

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

并添加此行

xdebug.max_nesting_level = 200


或这个

xdebug.max_nesting_level = -1

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

`


12

可能是因为xdebug。

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

  ";xdebug.max_nesting_level"


2
或禁用了所有xdebug
zloctb 2013年

2
这将如何运作?如果您没有手动定义限制,则它将恢复为默认值100(xdebug.org/docs/basic)。通过注释掉该行,您所做的所有事情都会将设置恢复为默认值。
justanotherprogrammer 2013年

如果您依赖他的工具,建议不要禁用所有xdebug。通常使用配置“ xdebug.max_nesting_level”时不知道其实际用途,因此通常仅注释就足够有效。
vandersondf

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的测试,以查看是否有效。

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

很好,第一个提到xdebug有一个单独.ini文件的答案。顺便说一句,当您运行php5-fpm时,此文件可能在此处:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan

7

php.ini:

xdebug.max_nesting_level = -1

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


有用!不管您是否使用XDebug,都不要在php.ini中注释掉行。我明确使用了:ini_set('xdebug.max_nesting_level',-1);
user2928048'5

6

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


5

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

例如:您定义了有限数量的插槽(例如100个),并监视分配给每个插槽/某些插槽的“工人”的数量。如果有空位可用,则将等待的工作人员“放入其中”。


1
这实际上不是普遍适用的方法。并行化更明智,而不是避免堆栈深度。
aredridel

5

从命令行检查递归:

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

如果结果> 100 THEN,则检查内存限制;


3

如果您使用的是Laravel,请执行

composer update

这应该是工作。


您应该添加有关此的更多背景信息。尽管laracasts.com/forum/…
ggderas,

1
这与xdebug / php.ini设置无关,这可能是导致错误的原因。您的应用程序也有可能处于dos循环中,并不断在一个函数中循环,没有OP在何处声明他们正在使用laravel并查看他的代码饮可能是codeigniter
James Kirkby

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

PS将9999更改为所需的任何数字。


1

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


1

在您的情况下,肯定是搜寻器实例具有更多的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,但没有帮助。无论如何,请检查您的类名或代码以进行正确的函数调用。


是答案还是问题?
AL

@daniedad我编辑了您的答案,我认为最好用文本而不是仅在代码附加的注释中编写解决方案。现在的表格使我觉得这是一个新问题,而不是一个答案。如果您不同意更改,请随时回滚。
AL

1

我在cloud9上遇到了WordPress的问题。原来是W3缓存插件。我禁用了插件,它运行良好。


1

如果您在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


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!


0

我有同样的问题,我喜欢这样:

打开MySQL my.ini文件

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

保存文件并尝试启动MySQL

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.