深入解析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 相关文章推荐
Access数据库导入Mysql的方法之一
Oct 09 PHP
PHP mkdir()定义和用法
Jan 14 PHP
对squid中refresh_pattern的一些理解和建议
Apr 17 PHP
php中大括号作用介绍
Mar 22 PHP
使用php get_headers 判断URL是否有效的解决办法
Apr 27 PHP
PHP遍历并打印指定目录下所有文件实例
Feb 10 PHP
php设置静态内容缓存时间的方法
Dec 01 PHP
php文件缓存方法总结
Mar 16 PHP
深入浅出讲解:php的socket通信原理
Dec 03 PHP
yii2实现分页,带搜索的分页功能示例
Jan 07 PHP
php基于 swoole 实现的异步处理任务功能示例
Aug 13 PHP
PHP遍历数组的6种方式总结
Nov 17 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
MySQL GBK→UTF-8编码转换
2007/05/24 PHP
PHP 匿名函数与注意事项详细介绍
2016/11/26 PHP
Nigma vs Alliance BO5 第三场2.14
2021/03/10 DOTA
Javascript SHA-1:Secure Hash Algorithm
2006/12/20 Javascript
Extjs学习笔记之五 一个小细节renderTo和applyTo的区别
2010/01/07 Javascript
jQuery 第二课 操作包装集元素代码
2010/03/14 Javascript
javascript复制对象使用说明
2011/06/28 Javascript
jQuery EasyUI API 中文文档 DateTimeBox日期时间框
2011/10/16 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
jquery 中toggle的2种用法详解(推荐)
2016/09/02 Javascript
js 判断数据类型的几种方法
2017/01/13 Javascript
Angular网络请求的封装方法
2018/05/22 Javascript
vue生成token并保存到本地存储中
2018/07/17 Javascript
使用Angular Cli如何创建Angular私有库详解
2019/01/30 Javascript
微信小程序实现列表滚动头部吸顶的示例代码
2020/07/12 Javascript
[59:15]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第一场 11.20
2020/11/20 DOTA
[03:11]完美世界DOTA2联赛PWL DAY8集锦
2020/11/09 DOTA
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
Python单例模式实例分析
2015/01/14 Python
利用Python开发实现简单的记事本
2016/11/15 Python
python实现神经网络感知器算法
2017/12/20 Python
python正则表达式之对号入座篇
2018/07/24 Python
Django Celery异步任务队列的实现
2019/07/24 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
基于python plotly交互式图表大全
2019/12/07 Python
python时间日期操作方法实例小结
2020/02/06 Python
解决python父线程关闭后子线程不关闭问题
2020/04/25 Python
如何用python批量调整视频声音
2020/12/22 Python
西安当代医院管理研究院笔试题
2015/12/11 面试题
通用自荐信范文
2014/03/14 职场文书
投资建议书模板
2014/05/12 职场文书
商务英语专业毕业生求职信
2014/07/06 职场文书
违纪开除通知书
2015/04/25 职场文书
2015年学校精神文明工作总结
2015/05/27 职场文书
比赛口号霸气押韵
2015/12/24 职场文书
如何理解python接口自动化之logging日志模块
2021/06/15 Python