“致命错误:已达到 '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(' ', $depth * 2)
. '<b> ->' . strtr($curr_key, $_replace) . '</b> = '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
之后:
$max_depth = 10;
$results .= '<br>' . str_repeat(' ', $depth * 2)
. '<b> ->' . 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 中的主要内容,如果未能解决你的问题,请参考以下文章