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利用COM对象访问SQLServer、Access
Oct 09 PHP
php5 mysql分页实例代码
Apr 10 PHP
PHP+Mysql+jQuery实现动态展示信息
Oct 08 PHP
php 记录进行累加并显示总时长为秒的结果
Nov 04 PHP
浅析PHP安装扩展mcrypt以及相关依赖项(PHP安装PECL扩展的方法)
Jul 05 PHP
ThinkPHP的L方法使用简介
Jun 18 PHP
PHP+shell实现多线程的方法
Jul 01 PHP
php 实现301重定向跳转实例代码
Jul 18 PHP
详解配置 Apache 服务器支持 PHP 文件的解析
Feb 15 PHP
PHP实现登录注册之BootStrap表单功能
Sep 03 PHP
php操作mongodb封装类与用法实例
Sep 01 PHP
详解使用php-cs-fixer格式化代码
Sep 16 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
linux下 C语言对 php 扩展
2008/12/14 PHP
解析PHP获取当前网址及域名的实现代码
2013/06/23 PHP
用PHP代替JS玩转DOM的思路及示例代码
2014/06/15 PHP
php+mysql结合Ajax实现点赞功能完整实例
2015/01/30 PHP
PHP编程实现csv文件导入mysql数据库的方法
2017/04/29 PHP
Jquey拖拽控件Draggable使用方法(asp.net环境)
2010/09/28 Javascript
JS获取节点的兄弟,父级,子级元素的方法
2014/01/09 Javascript
Struts2+jquery.form.js实现图片与文件上传的方法
2016/05/05 Javascript
深入理解js函数的作用域与this指向
2016/05/28 Javascript
Javascript字符串拼接小技巧(推荐)
2016/06/02 Javascript
Javascript的动态增加类的实现方法
2016/10/20 Javascript
JavaScript数据类型的存储方法详解
2017/08/25 Javascript
详解tween.js 中文使用指南
2018/01/05 Javascript
Angular6 用户自定义标签开发的实现方法
2019/01/08 Javascript
Node.js 多进程处理CPU密集任务的实现
2019/05/26 Javascript
vue 父组件通过$refs获取子组件的值和方法详解
2019/11/07 Javascript
python使用循环实现批量创建文件夹示例
2014/03/25 Python
python网络编程学习笔记(九):数据库客户端 DB-API
2014/06/09 Python
Python与shell的3种交互方式介绍
2015/04/11 Python
Python 包含汉字的文件读写之每行末尾加上特定字符
2016/12/12 Python
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
2017/08/18 Python
Python数据结构与算法之图结构(Graph)实例分析
2017/09/05 Python
Python数据结构之哈夫曼树定义与使用方法示例
2018/04/22 Python
Python画图实现同一结点多个柱状图的示例
2019/07/07 Python
python如何实现不用装饰器实现登陆器小程序
2019/12/14 Python
Django多层嵌套ManyToMany字段ORM操作详解
2020/05/19 Python
基于Python制作一副扑克牌过程详解
2020/10/19 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
2020/11/17 Python
html5-Canvas可以在web中绘制各种图形
2012/12/26 HTML / CSS
汇集了世界上最好的天然和有机美容产品:LoveLula
2018/02/05 全球购物
澳大利亚领先的在线机械五金、园艺和存储专家:Edisons
2018/03/24 全球购物
介绍一下Java中的static关键字
2012/05/12 面试题
经理秘书岗位职责
2013/11/14 职场文书
学术会议欢迎词
2014/01/09 职场文书
搞笑爱情保证书
2014/04/29 职场文书
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android