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

Posted

技术标签:

【中文标题】“致命错误:已达到 \'100\' 的最大函数嵌套级别,正在中止!”的解决方案在 PHP 中【英文标题】:Solution for "Fatal error: Maximum function nesting level of '100' reached, aborting!" in PHP“致命错误:已达到 '100' 的最大函数嵌套级别,正在中止!”的解决方案在 PHP 中 【发布时间】:2012-01-29 04:14:22 【问题描述】:

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

然而,php返回这个错误:

致命错误:达到“100”的最大函数嵌套级别, 中止!在 D:\wamp\www\crawler1\simplehtmldom_1_5\simple_html_dom.php 上线 第1355章

我在这里找到了解决方案:Increasing nesting function calls limit,但这不适用于我的情况。

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

“您是否安装了 Zend、IonCube 或 xDebug?如果是,您可能会从那里收到此错误。

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

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

【问题讨论】:

另外:PHP 对嵌套函数调用没有限制,它必须是您正在使用的扩展导致此问题。 @Abel 我确信我的代码没有错误。有一个静态变量,它在每次递归调用时将其值加一。如果该变量小于 100,则递归调用将继续,直到变量达到 100。我的意思是说,达到 100 的变量实际上是基本情况。虽然错误出现在 100 次递归之前。正如您所提到的,某些扩展是我造成的,我想提一下我正在使用来自 simple_html_dom.php 的函数。如果您对 simple_html_dom.php 有任何想法,请在这方面帮助我。请参考更新后的问题。 这是 xdebug 的错误。从屏幕截图中可以看出您使用的是 xdebug。您可以在此处禁用该设置:xdebug.max_nesting_level 或告知嵌套级别有多大。 如果使用 WAMP,请注意在 php.ini 中禁用 xdebug 并不总是有效;同样适用于允许嵌套的扩展级别;一个错误一个猜测;解决方案:转到 php.ini 并注释掉 php_xdebug-???.dll Increasing nesting functions calls limit的可能重复 【参考方案1】:

php.ini 中增加xdebug.max_nesting_level 的值

【讨论】:

@A.L 您编辑 php.ini 文件并在 XDebug 部分添加或编辑 xdebug.max_nesting_level 行。 但是,如果这是生产环境,请参阅接受的答案,即在该环境中禁用 xdebug。 这解决了症状(暂时),但不是问题。 当我在 MAMP 上使用 UFront for Haxe 时,此解决方案对我有用。 无限:xdebug.max_nesting_level = -1【参考方案2】:

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

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

在我的php.ini 文件中。这个扩展将堆栈限制为100,所以我禁用了它。递归函数现在按预期工作。

【讨论】:

所以,最终它毕竟是 XDebug 扩展......很高兴知道。如果您愿意,两天后您可以接受自己的答案作为已接受的答案(并查看您之前的问题,大多数都错过了已接受的答案)。 处理过度递归肯定比关闭监控要好。 这是一种严厉的做法。上面提到调整最大堆栈深度的变量的答案是一种更好的方法。 你不应该在生产环境中启用 xdebug。 天哪。我不能停止嘲笑选择的解决方案。所以我的电脑不会停止发出噪音,所以我找到了解决方案。把它关掉。 :)【参考方案3】:

与其进行递归函数调用,不如使用队列模型来扁平化结构。

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

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

【讨论】:

使用 SPL,您无需重新发明队列:php.net/manual/en/class.splqueue.php SPL 队列可能会提供更快的速度,但我喜欢在大多数简单任务中坚持使用数组。 push/pop/shift/unshift 都提供了。 这是正确答案。避免更改默认值。尝试优化您的代码。【参考方案4】:

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

【讨论】:

也可以在 php 中进行,例如在项目的配置文件中。 ini_set('xdebug.max_nesting_level', 200); @htxryan 我不是专家,但这是由于您的调用堆栈太“深”(调用其他函数的函数太多)。发生这种情况的典型场景是使用递归函数。该设置最有可能避免由于代码中的错误而导致“失控”递归。 @svas-s-r 您可能想考虑将该提示作为单独的答案添加或添加到现有的答案中,这对我很有帮助,但在 cmets 中几乎错过了 @Bryan 刚刚添加了答案【参考方案5】:

您可以设置上限,而不是禁用 xdebug,例如

xdebug.max_nesting_level=500

【讨论】:

@SebastianMach:令人惊讶的是,多年后也是如此。 :) (大概还有四次左右。人们不仅现在不阅读,甚至不再滚动。) @Sz.: 哇,过去的爆炸声:P 令人震惊。【参考方案6】:

也可以直接在 php 中解决这个问题,例如在项目的配置文件中。

ini_set('xdebug.max_nesting_level', 200);

【讨论】:

谢谢,这很好用,因为我不必担心更新我所有开发盒上的 php.ini,我只需将它添加到我的应用程序的引导文件中。 这是处理多个开发环境时的最佳解决方案!谢谢【参考方案7】:

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

xdebug.max_nesting_level=100

类似于:

xdebug.max_nesting_level=200

【讨论】:

【参考方案8】:

在使用 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,您不必担心更改嵌套级别的值。

`

【讨论】:

【参考方案9】:

可能是因为 xdebug 而发生的。

尝试在您的 "php.ini" 中注释以下行并重新启动服务器以重新加载 PHP。

  ";xdebug.max_nesting_level"

【讨论】:

或禁用所有xdebug 这将如何工作?如果您不手动定义限制,它将恢复为默认值,即 100 (xdebug.org/docs/basic)。通过注释掉这一行,你所做的一切都会强制设置恢复为默认值。 如果依赖他使用的工具,不建议禁用所有xdebug;通常配置“xdebug.max_nesting_level”是在不知道他的实际用途的情况下使用的,所以一般只有注释就足够了。【参考方案10】:

尝试在 /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();'

【讨论】:

太好了,第一个提到 xdebug 有一个单独的 .ini 文件的答案。顺便说一下,当你运行 php5-fpm 时,这个文件可能就在这里:/etc/php5/fpm/conf.d/20-xdebug.ini【参考方案11】:

php.ini:

xdebug.max_nesting_level = -1

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

【讨论】:

有效!不管你有没有使用XDebug,也不管你在php.ini 中注释掉一行。我明确使用了:ini_set('xdebug.max_nesting_level', -1);【参考方案12】:

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

【讨论】:

【参考方案13】:

从命令行检查递归:

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

if result > 100 THEN 检查内存限制;

【讨论】:

【参考方案14】:

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

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

【讨论】:

这并不是一个真正普遍适用的方法。并行化更明智,而不是避免堆栈深度。【参考方案15】:
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

附:将 9999 更改为您想要的任何数字。

【讨论】:

【参考方案16】:

如果你正在使用 Laravel,请这样做

composer update

这应该可以了。

【讨论】:

您应该添加更多有关此的背景信息。尽管laracasts.com/forum/… 这可能很有用 这与可能导致错误的 xdebug/php.ini 设置无关。也有可能您的应用程序处于 dos 循环中并不断循环围绕一个函数,OP 没有声明他们在哪里使用 laravel 并查看他的代码 sip 它可能是 codeigniter【参考方案17】:

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

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

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

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);,它仍然会在您的日志中打印出相同的错误消息。

【讨论】:

【参考方案18】:

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

【讨论】:

是答案还是问题? @daniedad 我编辑了您的答案,我认为最好用文本而不是仅在附加到代码的 cmets 中编写 solution。而现在的形式让我觉得这是一个新问题,而不是一个答案。如果您不同意更改,请随时回滚。【参考方案19】:

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

【讨论】:

【参考方案20】:

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

【讨论】:

【参考方案21】:

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

【讨论】:

【参考方案22】:

您还可以修改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 问题!

【讨论】:

【参考方案23】:

我遇到了同样的问题,我是这样解决的:

打开 mysql my.ini 文件 在 [mysqld] 部分中,添加以下行:innodb_force_recovery = 1 保存文件并尝试启动 MySQL 删除刚刚添加的那一行并保存

【讨论】:

以上是关于“致命错误:已达到 '100' 的最大函数嵌套级别,正在中止!”的解决方案在 PHP 中的主要内容,如果未能解决你的问题,请参考以下文章