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 09 PHP
Apache2 httpd.conf 中文版
Nov 17 PHP
php桌面中心(四) 数据显示
Mar 11 PHP
如何取得中文字符串中出现次数最多的子串
Aug 08 PHP
php中生成随机密码的自定义函数代码
Oct 21 PHP
ThinkPHP验证码使用简明教程
Mar 05 PHP
WordPress的文章自动添加关键词及关键词的SEO优化
Mar 01 PHP
php查询及多条件查询
Feb 26 PHP
Yii2设置默认控制器的两种方法
May 19 PHP
php实现算术验证码功能
Dec 05 PHP
PHP的介绍以及优势详细分析
Sep 05 PHP
PHP连接SQL server数据库测试脚本运行实例
Aug 24 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应用提速面面观
2006/10/09 PHP
PHP 应用程序的安全 -- 不能违反的四条安全规则
2006/11/26 PHP
9段PHP实用功能的代码推荐
2014/10/14 PHP
php实现获取文件mime类型的方法
2015/02/11 PHP
WordPress主题中添加文章列表页页码导航的PHP代码实例
2015/12/22 PHP
CodeIgniter控制器之业务逻辑实例分析
2016/01/20 PHP
thinkPHP多语言切换设置方法详解
2016/11/11 PHP
Laravel关联模型中过滤结果为空的结果集(has和with区别)
2018/10/18 PHP
基于php+MySql实现学生信息管理系统实例
2020/08/04 PHP
setTimeout和setInterval的区别你真的了解吗?
2011/03/31 Javascript
详解JavaScript基于面向对象之继承实例
2015/12/16 Javascript
JavaScript小技巧整理
2015/12/30 Javascript
AngularJS基础 ng-init 指令简单示例
2016/08/02 Javascript
详解如何让InstantClick兼容MathJax、百度统计等
2017/09/12 Javascript
ReactJS实现表单的单选多选和反选的示例
2017/10/13 Javascript
基于rollup的组件库打包体积优化小结
2018/06/18 Javascript
vue中axios的二次封装实例讲解
2019/10/14 Javascript
js实现简单掷骰子效果
2019/10/24 Javascript
浅谈vue异步数据影响页面渲染
2019/10/29 Javascript
在 Python 应用中使用 MongoDB的方法
2017/01/05 Python
Jupyter中直接显示Matplotlib的图形方法
2018/05/24 Python
Python过滤txt文件内重复内容的方法
2018/10/21 Python
详解用python写网络爬虫-爬取新浪微博评论
2019/05/10 Python
python中with语句结合上下文管理器操作详解
2019/12/19 Python
Python如何获取文件指定行的内容
2020/05/27 Python
Python selenium模块实现定位过程解析
2020/07/09 Python
Python pexpect模块及shell脚本except原理解析
2020/08/03 Python
Python如何实现Paramiko的二次封装
2021/01/30 Python
印度网上药店:1mg
2017/10/13 全球购物
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
汽车销售顾问求职自荐信
2014/01/01 职场文书
安全第一课观后感
2015/06/18 职场文书
干部培训简讯
2015/07/20 职场文书
JavaScript高级程序设计之变量与作用域
2021/11/17 Javascript
Win11 KB5015814遇安装失败 影响开始菜单性能解决方法
2022/07/15 数码科技
前端canvas中物体边框和控制点的实现示例
2022/08/05 Javascript