深入解析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 相关文章推荐
如何去掉文章里的 html 语法
Oct 09 PHP
main.php
Dec 09 PHP
libmysql.dll与php.ini是否真的要拷贝到c:\windows目录下呢
Mar 15 PHP
整理的9个实用的PHP库简介和下载
Nov 09 PHP
php中Smarty模板初体验
Aug 08 PHP
纯PHP生成的一个树叶图片画图例子
Apr 16 PHP
PHP函数eval()介绍和使用示例
Aug 20 PHP
html静态页面调用php文件的方法
Nov 13 PHP
php从csv文件读取数据并输出到网页的方法
Mar 14 PHP
php中PDO方式实现数据库的增删改查
May 17 PHP
深入浅析php json 格式控制
Dec 24 PHP
PHP使用Session实现上传进度功能详解
Aug 06 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
星际争霸 Starcraft 发展史
2020/03/14 星际争霸
php IP及IP段进行访问限制的代码
2008/12/17 PHP
从康盛产品(discuz)提取出来的模板类
2011/06/28 PHP
php数据访问之增删改查操作
2016/05/09 PHP
PHP如何防止XSS攻击与XSS攻击原理的讲解
2019/03/22 PHP
Laravel框架中缓存的使用方法分析
2019/09/06 PHP
利用ASP发送和接收XML数据的处理方法与代码
2007/11/13 Javascript
Script的加载方法小结
2011/01/12 Javascript
jQuery Ajax 实例全解析
2011/04/20 Javascript
判断对象是否Window的实现代码
2012/01/10 Javascript
jQuery右下角旋转环状菜单特效代码
2015/08/10 Javascript
JavaScript实现简洁的俄罗斯方块完整实例
2016/03/01 Javascript
jQuery Mobile中的button按钮组件基础使用教程
2016/05/23 Javascript
利用JS实现点击按钮后图片自动切换的简单方法
2016/10/24 Javascript
JS中关于事件处理函数名后面是否带括号的问题
2016/11/16 Javascript
javascript 初学教程及五子棋小程序的简单实现
2017/07/04 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
利用H5api实现时钟的绘制(javascript)
2020/09/13 Javascript
python去掉字符串中重复字符的方法
2014/02/27 Python
分析Python的Django框架的运行方式及处理流程
2015/04/08 Python
PyQt5打开文件对话框QFileDialog实例代码
2018/02/07 Python
python使用turtle库与random库绘制雪花
2018/06/22 Python
关于PyTorch源码解读之torchvision.models
2019/08/17 Python
python Web flask 视图内容和模板实现代码
2019/08/23 Python
tensorflow模型保存、加载之变量重命名实例
2020/01/21 Python
python实现企业微信定时发送文本消息的实例代码
2020/11/25 Python
用python对oracle进行简单性能测试
2020/12/05 Python
python 实现Harris角点检测算法
2020/12/11 Python
美国顶级防滑鞋:Shoes For Crews
2017/03/27 全球购物
雷蛇美国官网:Razer
2020/04/03 全球购物
毕业生的自我鉴定
2013/10/29 职场文书
中专生自我鉴定范文
2014/02/02 职场文书
法人授权委托书
2014/04/03 职场文书
企业党员岗位承诺书
2015/04/27 职场文书
新郎父母婚礼致辞
2015/07/27 职场文书
MySQL 使用SQL语句修改表名的实现
2021/04/07 MySQL