深入解析PHP垃圾回收机制对内存泄露的处理


Posted in PHP onJune 14, 2013

上次说到了refcount和is_ref,这里来说说内存泄露的情况

$a = array(1, 2, &$a);
unset($a);

在老的PHP版本中,这里就会出现内存泄露,分析如下:

执行第一行,可以知道$a和$a[2]指向的zval refcount=2,is_ref=1

然后执行第二行,$a将会从符号表中被删除,同时指向的zval的refcount--,此时refcount=1,因为refcount!=0,故此zval不会被当做垃圾回收,但是此时我们却失去了$a[2]指向这个zval的入口,因此这个zval成了一块内存垃圾

同样的道理可以发生在类内部引用里,例如

$a = new Man();
$a->self = &$a;
unset($a);

那么如何解决这种问题呢,新的GC机制采用了一个算法来解决这个问题

PHP有一个root buffer用来存储zval的节点信息,当root buffer满了或者手动调用gc函数时,GC算法启动

对于一个数组或者类类型的zval而言,在垃圾回收机制启动时,算法会对该zval的数组/类内部的元素/成员的zval进行一次遍历并将refcount减1,如果说遍历完成后该zval的refcount被减为0,则说明这个zval是一个内存垃圾,他将被销毁,见下面的例子

$a = array(1, 2, &$a, &$a);
unset($a);

容易知道$a指向的zval,假设为z1的refcount=3,is_ref=1

当unset($a)执行的时候,$a就已经从符号表中删去,同时我们也失去了访问z1的入口,此时z1 refcount=2,is_ref=1

当GC启动时,会对该z1的数组元素的zval的refcount进行遍历减1,遍历到a[2]时,z1 refcount--, a[3]时 z1 refcount--,此时z1 refcount = 0,即可将z1标记为内存垃圾,算法后将其回收

总结来说可以这么表述:若一个数组类型的zval,对他的元素zval进行一次遍历,同时将遍历到的zval的refcount--,如果最后refcount=0的zval,就是垃圾,需要被回收

PHP 相关文章推荐
用PHP编程开发“虚拟域名”系统
Oct 09 PHP
ThinkPHP模板中判断volist循环的最后一条记录的验证方法
Jul 01 PHP
ThinkPHP的MVC开发机制实例解析
Aug 23 PHP
thinkphp3.2.2实现生成多张缩略图的方法
Dec 19 PHP
对PHP PDO的一些认识小结
Jan 23 PHP
php中有关合并某一字段键值相同的数组合并的改进
Mar 10 PHP
php以fastCGI的方式运行时文件系统权限问题及解决方法
May 11 PHP
WordPress中用于获取及自定义头像图片的PHP脚本详解
Dec 17 PHP
php的debug相关函数用法示例
Jul 11 PHP
PHP判断json格式是否正确的实现代码
Sep 20 PHP
PHP实现可添加水印与生成缩略图的图片处理工具类
Jan 16 PHP
php实现有序数组旋转后寻找最小值方法
Sep 27 PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
Jun 14 #PHP
解析php中两种缩放图片的函数,为图片添加水印
Jun 14 #PHP
PHP操作Memcache实例介绍
Jun 14 #PHP
解析PHP处理换行符的问题 \r\n
Jun 13 #PHP
基于PHP5魔术常量与魔术方法的详解
Jun 13 #PHP
基于PHPExcel的常用方法总结
Jun 13 #PHP
深入PHP FTP类的详解
Jun 13 #PHP
You might like
有关php运算符的知识大全
2011/11/03 PHP
php class中self,parent,this的区别以及实例介绍
2013/04/24 PHP
解析PHP缓存函数的使用说明
2013/05/10 PHP
CI框架中数据库操作函数$this->db->where()相关用法总结
2016/05/17 PHP
PHP封装的XML简单操作类完整实例
2017/11/13 PHP
一个关于jqGrid使用的小例子(行按钮)
2011/11/04 Javascript
验证手机号码的JS方法分享
2013/09/10 Javascript
js setTimeout opener的用法示例详解
2013/10/23 Javascript
JavaScript简单实现网页回到顶部功能
2013/11/12 Javascript
js对文章内容进行分页示例代码
2014/03/05 Javascript
JS实现判断碰撞的方法
2015/02/11 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
2015/09/12 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
JS/jQ实现免费获取手机验证码倒计时效果
2016/06/13 Javascript
基于Javascript实现的不重复ID的生成器
2016/12/25 Javascript
AngularJs每天学习之总体介绍
2017/08/07 Javascript
教你30秒发布一个TypeScript包到NPM的方法步骤
2019/07/22 Javascript
js实现时分秒倒计时
2019/12/03 Javascript
Vue-router 报错NavigationDuplicated的解决方法
2020/03/31 Javascript
js实现简单音乐播放器
2020/06/30 Javascript
swiper4实现移动端导航栏tab滑动切换
2020/10/16 Javascript
[27:02]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第三场
2014/05/24 DOTA
[00:21]DOTA2亚洲邀请赛 Logo演绎
2015/02/07 DOTA
Python处理CSV与List的转换方法
2018/04/19 Python
解决Mac下首次安装pycharm无project interpreter的问题
2018/10/29 Python
python给图像加上mask,并提取mask区域实例
2020/01/19 Python
pip安装tensorflow的坑的解决
2020/04/19 Python
浅谈Python里面None True False之间的区别
2020/07/09 Python
python -v 报错问题的解决方法
2020/09/15 Python
Python 用__new__方法实现单例的操作
2020/12/11 Python
女士鞋子、包包和服装在线,第一款10美元:ShoeDazzle
2019/07/26 全球购物
反邪教警示教育方案
2014/05/13 职场文书
临床专业自荐信
2014/06/22 职场文书
班级学雷锋活动总结
2014/06/26 职场文书
活动新闻稿范文
2015/07/17 职场文书
MySQL使用IF语句及用case语句对条件并结果进行判断 
2022/09/23 MySQL