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调用MsSQL Server 2012存储过程获取多结果集(包含output参数)的详解
Jul 03 PHP
MyEclipse常用配置图文教程
Sep 11 PHP
PHP解析目录路径的3个函数总结
Nov 18 PHP
Thinkphp调用Image类生成缩略图的方法
Mar 07 PHP
解决ThinkPHP关闭调试模式时报错的问题汇总
Apr 22 PHP
php使用Jpgraph绘制饼状图的方法
Jun 10 PHP
PHP实现图片自动清理的方法
Jul 08 PHP
最新制作ThinkPHP3.2.3完全开发手册
Nov 23 PHP
CI框架实现cookie登陆的方法详解
May 18 PHP
解决form中action属性后面?传递参数 获取不到的问题
Jul 21 PHP
Laravel构建即时应用的一种实现方法详解
Aug 31 PHP
解决Laravel 使用insert插入数据,字段created_at为0000的问题
Oct 11 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
2.PHP入门
2006/10/09 PHP
php开启安全模式后禁用的函数集合
2011/06/26 PHP
PHP正确配置mysql(apache环境)
2011/08/28 PHP
深入apache配置文件httpd.conf的部分参数说明
2013/06/28 PHP
php格式化时间戳显示友好的时间实现思路及代码
2014/10/23 PHP
PHP cURL初始化和执行方法入门级代码
2015/05/28 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
jquery实现textarea 高度自适应
2015/03/11 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
2016/08/20 Javascript
利用jsonp跨域调用百度js实现搜索框智能提示
2016/08/24 Javascript
JS实现微信弹出搜索框 多条件查询功能
2016/12/13 Javascript
Vue项目webpack打包部署到服务器的实例详解
2017/07/17 Javascript
原生js实现简单的焦点图效果实例
2017/12/14 Javascript
js代码编写无缝轮播图
2020/09/13 Javascript
vue项目实现多语言切换的思路
2020/09/17 Javascript
Python设计足球联赛赛程表程序的思路与简单实现示例
2016/06/28 Python
详解使用 pyenv 管理多个版本 python 环境
2017/10/19 Python
Python操作配置文件ini的三种方法讲解
2019/02/22 Python
Python基础之函数原理与应用实例详解
2020/01/03 Python
TensorFlow2.X使用图片制作简单的数据集训练模型
2020/04/08 Python
对Keras中predict()方法和predict_classes()方法的区别说明
2020/06/09 Python
Keras自定义IOU方式
2020/06/10 Python
python 发送邮件的四种方法汇总
2020/12/02 Python
Nike英国官网:Nike.com (UK)
2017/02/13 全球购物
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
飞利浦法国官网:Philips法国
2019/07/10 全球购物
水务局局长岗位职责
2013/11/28 职场文书
办公室主任先进事迹
2014/01/18 职场文书
小学毕业寄语大全
2014/04/03 职场文书
音乐兴趣小组活动总结
2014/07/07 职场文书
出售房屋协议书范本
2014/10/06 职场文书
租房协议书范例
2014/10/14 职场文书
搬迁通知
2015/04/20 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
元旦晚会主持词开场白
2015/05/28 职场文书
Oracle中update和select 关联操作
2022/01/18 Oracle