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过滤危险html代码
Aug 18 PHP
解析htaccess伪静态的规则
Jun 18 PHP
php curl_init函数用法
Jan 31 PHP
PHP中鲜为人知的10个函数
Feb 28 PHP
php接口数据加密、解密、验证签名
Mar 12 PHP
PHP实现将textarea的值根据回车换行拆分至数组
Jun 10 PHP
PHP安装threads多线程扩展基础教程
Nov 17 PHP
php上传大文件设置方法
Apr 14 PHP
PHP解压ZIP文件到指定文件夹的方法
Nov 17 PHP
php插件Xajax使用方法详解
Aug 31 PHP
CI框架教程之优化验证码机制详解【验证码辅助函数】
Apr 16 PHP
PHP实现八皇后算法
May 06 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
解决了Ajax、MySQL 和 Zend Framework 的乱码问题
2009/03/03 PHP
提示Trying to clone an uncloneable object of class Imagic的解决
2011/10/27 PHP
浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
2013/06/18 PHP
php截取中文字符串不乱码的方法
2013/12/25 PHP
destoon实现不同会员组公司名称显示不同的颜色的方法
2014/08/22 PHP
PHP符合PSR编程规范的实例分享
2016/12/21 PHP
javascript读取xml
2006/11/04 Javascript
JavaScript 异步调用框架 (Part 5 - 链式实现)
2009/08/04 Javascript
jquery中使用ajax获取远程页面信息
2011/11/13 Javascript
JavaScript采用递归算法计算阶乘实例
2015/08/04 Javascript
简单介绍JavaScript数据类型之隐式类型转换
2015/12/28 Javascript
浅谈javascript的call()、apply()、bind()的用法
2016/02/21 Javascript
JavaScript实现斗地主游戏的思路
2016/02/29 Javascript
轻松掌握JavaScript中的Math object数学对象
2016/05/26 Javascript
全面了解javascript中的错误处理机制
2016/07/18 Javascript
js实现界面向原生界面发消息并跳转功能
2016/11/22 Javascript
jquery mobile移动端幻灯片滑动切换效果
2020/04/15 Javascript
Angular在一个页面中使用两个ng-app的方法
2017/02/20 Javascript
微信小程序实现锚点定位楼层跳跃的实例
2017/05/18 Javascript
layui button 按钮弹出提示窗口,确定才进行的方法
2019/09/06 Javascript
使用webpack搭建pixi.js开发环境
2020/02/12 Javascript
Python专用方法与迭代机制实例分析
2014/09/15 Python
100行Python代码实现自动抢火车票(附源码)
2018/01/11 Python
Python列表list排列组合操作示例
2018/12/18 Python
详解python日志输出使用配置文件格式
2021/02/10 Python
使用phonegap检测网络状态的方法
2017/03/30 HTML / CSS
使用css如何制作时间ICON方法实践
2012/11/12 HTML / CSS
Ariat官网:美国马靴和服装品牌
2019/12/16 全球购物
助学感谢信范文
2015/01/21 职场文书
学校艾滋病宣传活动总结
2015/05/09 职场文书
党支部意见范文
2015/06/02 职场文书
老干部座谈会主持词
2015/07/03 职场文书
2017元旦、春节期间廉洁自律承诺书
2016/03/25 职场文书
redis内存空间效率问题的深入探究
2021/05/17 Redis
Mysql systemctl start mysqld报错的问题解决
2021/06/03 MySQL
springboot如何接收application/x-www-form-urlencoded类型的请求
2021/11/02 Java/Android