深入解析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 相关文章推荐
3种平台下安装php4经验点滴
Oct 09 PHP
php array_intersect比array_diff快(附详细的使用说明)
Jul 03 PHP
php入门学习知识点七 PHP函数的基本应用
Jul 14 PHP
基于PHP开发中的安全防范知识详解
Jun 06 PHP
对于PHP 5.4 你必须要知道的
Aug 07 PHP
php第一次无法获取cookie问题处理
Dec 15 PHP
php中stdClass的用法分析
Feb 27 PHP
使用PHP生成图片的缩略图的方法
Aug 18 PHP
yii2实现 "上一篇,下一篇" 功能的代码实例
Feb 04 PHP
php redis实现对200w用户的即时推送
Mar 04 PHP
ThinkPHP框架表单验证操作方法
Jul 19 PHP
laravel框架与其他框架的详细对比
Oct 23 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 缓冲的免费实现方法
2006/10/09 PHP
Ext.data.PagingMemoryProxy分页一次性读取数据的实现代码
2010/04/07 PHP
myFocus slide3D v1.1.0 使用方法与下载
2011/01/12 Javascript
图片onload事件触发问题解决方法
2011/07/31 Javascript
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
2011/10/01 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
javascript闭包入门示例
2014/04/30 Javascript
javascript去掉代码里面的注释
2015/07/24 Javascript
JavaScript html5 canvas画布中删除一个块区域的方法
2016/01/26 Javascript
浅析jQuery Ajax请求参数和返回数据的处理
2016/02/24 Javascript
jQuery点击其他地方时菜单消失的实现方法
2016/04/22 Javascript
使用plupload自定义参数实现多文件上传
2016/07/19 Javascript
浅谈angular2路由预加载策略
2017/10/04 Javascript
详解create-react-app 自定义 eslint 配置
2018/06/07 Javascript
[54:28]EG vs OG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
python中的实例方法、静态方法、类方法、类变量和实例变量浅析
2014/04/26 Python
Python魔术方法详解
2015/02/14 Python
Python的collections模块中的OrderedDict有序字典
2016/07/07 Python
使用python绘制常用的图表
2016/08/27 Python
Python3实现从排序数组中删除重复项算法分析
2019/04/03 Python
python 动态迁移solr数据过程解析
2019/09/04 Python
Python树莓派学习笔记之UDP传输视频帧操作详解
2019/11/15 Python
Python计算机视觉里的IOU计算实例
2020/01/17 Python
python tkinter GUI绘制,以及点击更新显示图片代码
2020/03/14 Python
Python通过类的组合模拟街道红绿灯
2020/09/16 Python
python使用matplotlib:subplot绘制多个子图的示例
2020/09/24 Python
移动端HTML5实现文件上传功能【附代码】
2016/03/25 HTML / CSS
Html5页面二次分享的实现
2018/07/30 HTML / CSS
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
澳大利亚领先的女性运动服品牌:Lorna Jane
2020/06/19 全球购物
一道SQL面试题
2012/12/31 面试题
正风肃纪剖析材料
2014/02/18 职场文书
小学班主任事迹材料
2014/12/17 职场文书
军事理论课感想
2015/08/11 职场文书
2016党风廉政建设心得体会范文
2016/01/25 职场文书
mysql查询结果实现多列拼接查询
2022/04/03 MySQL