深入解析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 相关文章推荐
一个ORACLE分页程序,挺实用的.
Oct 09 PHP
PHP 采集程序 常用函数
Dec 18 PHP
PHP HTML代码串截取代码
Dec 29 PHP
phpmyadmin MySQL 加密配置方法
Jul 05 PHP
深入PHP购物车模块功能分析(函数讲解,附源码)
Jun 25 PHP
phpstorm编辑器乱码问题解决
Dec 01 PHP
PHP几个实用自定义函数小结
Jan 25 PHP
ThinkPHP中limit()使用方法详解
Apr 19 PHP
浅析php中array_map和array_walk的使用对比
Nov 20 PHP
PHP巧妙利用位运算实现网站权限管理的方法
Mar 12 PHP
万能的php分页类
Jul 06 PHP
PHP完全二叉树定义与实现方法示例
Oct 09 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
js模拟实现Array的sort方法
2007/12/11 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
一个js导致的jquery失效问题的解决方法
2013/11/27 Javascript
JavaScript中的Web worker多线程API研究
2014/12/06 Javascript
javascript 操作符(~、&、|、^、)使用案例
2014/12/31 Javascript
js 求时间差的实现代码
2016/04/26 Javascript
微信小程序 Template详解及简单实例
2017/01/05 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
2017/03/14 Javascript
JS排序之快速排序详解
2017/04/08 Javascript
深入浅析Node.js单线程模型
2017/07/10 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
使用Javascript简单计算器
2018/11/17 Javascript
NodeJs 实现简单WebSocket即时通讯的示例代码
2019/08/05 NodeJs
用JS实现一个简单的打砖块游戏
2019/12/11 Javascript
vue中echarts图表大小适应窗口大小且不需要刷新案例
2020/07/19 Javascript
跟老齐学Python之有容乃大的list(2)
2014/09/15 Python
Python中有趣在__call__函数
2015/06/21 Python
Python利用operator模块实现对象的多级排序详解
2017/05/09 Python
深入理解Django的中间件middleware
2018/03/14 Python
pycharm debug功能实现跳到循环末尾的方法
2018/11/29 Python
jupyter notebook 实现matplotlib图动态刷新
2020/04/22 Python
使用OpenCV对车道进行实时检测的实现示例代码
2020/06/19 Python
python图片验证码识别最新模块muggle_ocr的示例代码
2020/07/03 Python
在Python中实现字典反转案例
2020/12/05 Python
Python 实现RSA加解密文本文件
2020/12/30 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
2021/02/25 Python
日本无添加化妆品:HABA
2016/08/18 全球购物
Lookfantastic意大利官网:英国知名美妆购物网站
2019/05/31 全球购物
小学生获奖感言范文
2014/02/02 职场文书
校园安全检查制度
2014/02/03 职场文书
施工材料员岗位职责
2014/02/12 职场文书
创先争优活动承诺书
2014/08/30 职场文书
领导干部作风整顿个人剖析材料
2014/10/11 职场文书
2014年共青团工作总结
2014/12/10 职场文书
出国导师推荐信
2015/03/25 职场文书
刑事辩护词范文
2015/05/21 职场文书