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 smarty的预保留变量总结
Dec 04 PHP
PHP多线程抓取网页实现代码
Jul 22 PHP
php fsockopen伪造post与get方法的详解
Jun 14 PHP
php查看请求头信息获取远程图片大小的方法分享
Dec 25 PHP
CodeIgniter采用config控制的多语言实现根据浏览器语言自动转换功能
Jul 18 PHP
php面象对象数据库操作类实例
Dec 02 PHP
Windows7下的php环境配置教程
Feb 28 PHP
PHP使用NuSOAP调用Web服务的方法
Jul 18 PHP
PHP实现图片不变型裁剪及图片按比例裁剪的方法
Jan 14 PHP
PHP简单实现解析xml为数组的方法
May 02 PHP
PHP下载大文件失败并限制下载速度的实例代码
May 10 PHP
PHP的cookie与session原理及用法详解
Sep 27 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
PHP三元运算符的结合性介绍
2012/01/10 PHP
PHP Class&amp;Object -- PHP 自排序二叉树的深入解析
2013/06/25 PHP
php去除HTML标签实例
2013/11/06 PHP
php smtp实现发送邮件功能
2017/06/22 PHP
php屏蔽错误及提示的方法
2020/05/10 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
JavaScript 小型打飞机游戏实现原理说明
2010/10/28 Javascript
推荐30个新鲜出炉的精美 jQuery 效果
2012/03/26 Javascript
基于JS实现的倒计时程序实例
2015/07/24 Javascript
JS根据浏览器窗口大小实时动态改变网页文字大小的方法
2016/02/25 Javascript
JS函数arguments数组获得实际传参数个数的实现方法
2016/05/28 Javascript
浅析Javascript的自动分号插入(ASI)机制
2016/09/29 Javascript
js入门之Function函数的使用方法【新手必看】
2016/11/22 Javascript
Angular.JS通过指令操作DOM的方法
2017/05/10 Javascript
详解如何使用Node.js编写命令工具——以vue-cli为例
2017/06/29 Javascript
ng-alain表单使用方式详解
2018/07/10 Javascript
详解React项目中碰到的IE问题
2019/03/14 Javascript
JavaScript实现的联动菜单特效示例
2019/07/08 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
[01:47]2018年度DOTA2最具人气解说-完美盛典
2018/12/16 DOTA
Python使用Scrapy爬取妹子图
2015/05/28 Python
利用python发送和接收邮件
2016/09/27 Python
Diango + uwsgi + nginx项目部署的全过程(可外网访问)
2018/04/22 Python
Python Selenium 之数据驱动测试的实现
2019/08/01 Python
详解python常用命令行选项与环境变量
2020/02/20 Python
Django实现从数据库中获取到的数据转换为dict
2020/03/27 Python
使用html5制作loading图的示例
2014/04/14 HTML / CSS
学生党员思想汇报范文
2014/01/09 职场文书
大学学习生活感言
2014/01/18 职场文书
收银员的岗位职责范本
2014/02/04 职场文书
广告传媒专业应届生求职信
2014/03/01 职场文书
学生安全承诺书
2014/05/22 职场文书
拔河比赛口号
2014/06/10 职场文书
投标承诺函范文
2015/01/21 职场文书
市级三好生竞选稿
2015/11/21 职场文书