PHP中的函数嵌套层数限制分析


Posted in PHP onJune 13, 2011

函数嵌套,这个名字有点纠结,也许不太好理解。一个比较常见的函数嵌套特例:递归函数,即函数自己嵌套自己。 一直以为在PHP中不能有太多的函数嵌套,这是因为在以前某些时候不小心用到了递归,在递归的深度达到100时, 即函数嵌套的层数达到100时,程序会报一个 Fatal error。如下示例:

function rt() { 
static $i; 
echo $i++, '<br />'; 
rt(); 
} 
rt(); 
die();

在我的win7 + php5.3的环境下报错如下: Fatal error:Maximum function nesting level of ‘100′ reached, aborting!

一直以为是PHP本身的限制,直到某一天切换到liunx环境下以命令行的模式运行,发现,程序限入了死循环。 不同的环境下有不同的结果,为什么呢?好吧,我们直接在源码中查找报错信息,发现没有相关内容,直接debug整个执行过程,也没有在win下的报错。 什么原因?再次切换到win下,再次查找,发现在xdebug中看到了报错信息。在xdebug.c文件的1242行开始:

XG(level)++; 
if (XG(level) == XG(max_nesting_level)) { 
php_error(E_ERROR, "Maximum function nesting level of '%ld' reached, 
aborting!", XG(max_nesting_level)); 
}

这表示什么?之前的函数嵌套的层数限制是xdebug扩展加上的,为什么会有这个限制了呢?在xdebug中,xdebug中会记录每次函数调用, 包括嵌套的函数调用,函数调用中的内存,时间等值,这些值在分析程序性能时有大用。如果没有这个限制,当嵌套的层数太多,机器会内存耗尽。 如果这是一台生产环境的服务器,那么就会有部分服务不可用,当然生产环境下是不会添加这个扩展的。但是在多人共用的开发服务器上就可能有这个扩展, 如果因为一个开发人员的程序错误导致机器不可用,从而使所有的开发人员不能工作,我想这也许是添加限制的原因吧。

如果我们需要把这个限制的层数加大,怎么办呢?改源码,重新编译xdebug扩展?不需要,在xdebug的配置项中有一项叫做xdebug.max_nesting_level, 默认情况下,在php.ini中这个配置项是被注释了的,去掉注释,将这个值成你所需要的值,200?不够,那500吧,但是这个值还是不要太大, 如果递归太多,对程序的性能有很大的影响,此时,以栈的形式实现递归或者用循环替换递归会是一个更好的方案, 如:斐波那契数列(Fibonacci)的实现,用循环来实现会更快。

结论:PHP本身的函数嵌套是没有限制的,如果说有限制,也是内存的限制。这是因为PHP的函数嵌套是以栈的形式实现的。对于每个函数都会分配一段内存来存储函数局部的内容。

PHP 相关文章推荐
php更改目录及子目录下所有的文件后缀扩展名的代码
Oct 12 PHP
PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-1 开始了解php
Jul 03 PHP
ThinkPHP CURD方法之data方法详解
Jun 18 PHP
浅谈PDO的rowCount函数
Jun 18 PHP
使用phpstorm和xdebug实现远程调试的方法
Dec 29 PHP
thinkphp5.0自定义验证规则使用方法
Nov 16 PHP
自写的利用PDO对mysql数据库增删改查操作类
Feb 19 PHP
PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
May 21 PHP
ThinkPHP中图片按比例切割的代码实例
Mar 08 PHP
laravel5.1框架model类查询的实现方法
Oct 08 PHP
laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
Jan 25 PHP
tp5.1 框架数据库高级查询技巧实例总结
May 25 PHP
PHP5中新增stdClass 内部保留类
Jun 13 #PHP
php中使用Akismet防止垃圾评论的代码
Jun 10 #PHP
php中通过虚代理实现延迟加载的实现代码
Jun 10 #PHP
php获取后台Job管理的实现代码
Jun 10 #PHP
php下通过curl抓取yahoo boss 搜索结果的实现代码
Jun 10 #PHP
PHP缩略图等比例无损压缩,可填充空白区域补充色
Jun 10 #PHP
PHP网站备份程序代码分享
Jun 10 #PHP
You might like
Joomla调用系统自带编辑器的实现方法
2016/05/05 PHP
基于PHP实现短信验证码接口(容联运通讯)
2016/09/06 PHP
thinkPHP中volist标签用法示例
2016/12/06 PHP
PHP+JavaScript实现无刷新上传图片
2017/02/21 PHP
php简单计算权重的方法示例【适合抽奖类应用】
2019/06/10 PHP
php自动加载代码实例详解
2021/02/26 PHP
二级域名转向类
2006/11/09 Javascript
25个好玩的JavaScript小游戏分享
2011/04/22 Javascript
JS通过ajax动态读取xml文件内容的方法
2015/03/24 Javascript
JavaScript实现把数字转换成中文
2015/06/29 Javascript
纯css实现窗户玻璃雨滴逼真效果
2015/08/23 Javascript
jquery+css实现动感的图片切换效果
2015/11/25 Javascript
BootStrap glyphicons 字体图标实现方法
2016/05/01 Javascript
JS 对java返回的json格式的数据处理方法
2016/12/05 Javascript
JS字符串按逗号和回车分隔的方法
2017/04/25 Javascript
5 种JavaScript编码规范
2018/01/30 Javascript
jQuery中的$是什么意思及 $. 和 $().的区别
2018/04/20 jQuery
nodejs更改项目端口号的方法
2018/05/13 NodeJs
js纯前端实现腾讯cos文件上传功能的示例代码
2019/05/14 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
JavaScript this在函数中的指向及实例详解
2019/10/14 Javascript
django项目运行因中文而乱码报错的几种情况解决
2017/11/07 Python
Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】
2019/03/30 Python
Django项目使用CircleCI的方法示例
2019/07/14 Python
python 申请内存空间,用于创建多维数组的实例
2019/12/02 Python
解决pycharm上的jupyter notebook端口被占用问题
2019/12/17 Python
python如何使用Redis构建分布式锁
2020/01/16 Python
pytorch对梯度进行可视化进行梯度检查教程
2020/02/04 Python
利用CSS3实现开门效果实例源码
2016/08/22 HTML / CSS
英国和世界各地鲜花速递专家:Arena Flowers
2018/02/10 全球购物
马来西亚网上购物平台:ezbuy
2018/02/13 全球购物
当x.equals(y)等于true时,x.hashCode()与y.hashCode()可以不相等,这句话对不对
2015/05/02 面试题
生日宴会主持词
2014/03/20 职场文书
初中学生期末评语
2014/04/24 职场文书
2015新学期开学寄语
2015/02/26 职场文书
Python first-order-model实现让照片动起来
2022/06/25 Python