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中的时间显示
Jan 18 PHP
Dedecms常用函数解析
Feb 01 PHP
最新的php 文件上传模型,支持多文件上传
Aug 13 PHP
PHP在线调试执行的实现方法(附demo源码)
Apr 28 PHP
thinkPHP基于ajax实现的菜单与分页示例
Jul 12 PHP
ucenter中词语过滤原理分析
Jul 13 PHP
php断点续传之文件分割合并详解
Dec 13 PHP
php检查函数必传参数是否存在的实例详解
Aug 28 PHP
PHP测试框架PHPUnit组织测试操作示例
May 28 PHP
laravel + vue实现的数据统计绘图(今天、7天、30天数据)
Jul 31 PHP
php学习笔记之字符串常见操作总结
Jul 16 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 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
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
解决了Ajax、MySQL 和 Zend Framework 的乱码问题
2009/03/03 PHP
linux下为php添加curl扩展的方法
2011/07/29 PHP
php 运算符与表达式详细介绍
2016/11/30 PHP
使用JavaScript实现连续滚动字幕效果的方法
2015/07/07 Javascript
jquery图片轮播特效代码分享
2020/04/20 Javascript
基于javascript实现checkbox复选框实例代码
2016/01/28 Javascript
js检测离开或刷新页面时表单数据是否更改的方法
2016/08/02 Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
2016/11/04 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
全选复选框JavaScript编写小结(附代码)
2017/08/16 Javascript
jQuery实现动态控制页面元素的方法分析
2017/12/20 jQuery
JS实现把一个页面层数据传递到另一个页面的两种方式
2018/08/13 Javascript
总结javascript三元运算符知识点
2018/09/28 Javascript
详解vue开发中调用微信jssdk的问题
2019/04/16 Javascript
layui2.0使用table+laypage实现真分页
2019/07/27 Javascript
vue路由 遍历生成复数router-link的例子
2019/10/30 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
python 读写、创建 文件的方法(必看)
2016/09/12 Python
详解Python中for循环是如何工作的
2017/06/30 Python
python之Flask实现简单登录功能的示例代码
2018/12/24 Python
Python安装依赖(包)模块方法详解
2020/02/14 Python
Python实现UDP程序通信过程图解
2020/05/15 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
python selenium 获取接口数据的实现
2020/12/07 Python
阿联酋彩妆品牌:OUD MILANO
2019/10/06 全球购物
一些Solaris面试题
2013/03/22 面试题
社区党员先进事迹
2014/01/22 职场文书
商务日语专业毕业生自荐信
2014/03/27 职场文书
社会稳定风险评估方案
2014/06/02 职场文书
图书馆标语
2014/06/19 职场文书
语文教研活动总结
2014/07/02 职场文书
经典导游欢迎词
2015/01/26 职场文书
房屋产权证明书
2015/06/19 职场文书
Python 如何解决稀疏矩阵运算
2021/05/26 Python
使用logback实现按自己的需求打印日志到自定义的文件里
2021/08/30 Java/Android