深入解析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原理之异常机制
Aug 21 PHP
php5.3中连接sqlserver2000的两种方法(com与ODBC)
Dec 29 PHP
19个Android常用工具类汇总
Dec 30 PHP
PHP实现从远程下载文件的方法
Mar 12 PHP
php使用GD实现颜色渐变实例
Jun 02 PHP
使用PHPCMS搭建wap手机网站
Sep 20 PHP
分享ThinkPHP3.2中关联查询解决思路
Sep 20 PHP
Zend Framework教程之Bootstrap类用法概述
Mar 14 PHP
ThinkPHP连接Oracle数据库
Apr 22 PHP
学习thinkphp5.0验证类使用方法
Nov 16 PHP
PHP7扩展开发之hello word实现方法详解
Jan 15 PHP
解决laravel 表单提交-POST 异常的问题
Oct 15 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 模拟$_PUT实现代码
2010/03/15 PHP
php 智能404跳转代码,适合换域名没改变目录的网站
2010/06/04 PHP
用 JSON 处理缓存
2007/04/27 Javascript
基于jquery的loading效果实现代码
2010/11/05 Javascript
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
javascript中兼容主流浏览器的动态生成iframe方法
2014/05/05 Javascript
JavaScript资源预加载组件和滑屏组件的使用推荐
2016/03/10 Javascript
jQuery实现点击行选中或取消CheckBox的方法
2016/08/01 Javascript
React 实现拖拽功能的示例代码
2019/01/06 Javascript
详解微信小程序获取当前时间及日期的方法
2019/04/28 Javascript
vue 指令和过滤器的基本使用(品牌管理案例)
2019/11/04 Javascript
JS window对象简单操作完整示例
2020/01/14 Javascript
微信小程序实现发微博功能的示例代码
2020/06/24 Javascript
Vue切换组件实现返回后不重置数据,保留历史设置操作
2020/07/21 Javascript
[53:13]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-GAMING
2014/05/22 DOTA
[43:48]Ti4正赛第一天 VG vs NEWBEE 2
2014/07/19 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
python清除字符串里非数字字符的方法
2015/07/02 Python
详解python使用递归、尾递归、循环三种方式实现斐波那契数列
2018/01/16 Python
django用户注册、登录、注销和用户扩展的示例
2018/03/19 Python
Python实现的根据IP地址计算子网掩码位数功能示例
2018/05/23 Python
tensorflow 获取变量&打印权值的实例讲解
2018/06/14 Python
Python Opencv任意形状目标检测并绘制框图
2019/07/23 Python
python groupby 函数 as_index详解
2019/12/16 Python
Python实现手机号自动判断男女性别(实例解析)
2019/12/22 Python
Python直接赋值及深浅拷贝原理详解
2020/09/05 Python
python工具——Mimesis的简单使用教程
2021/01/16 Python
html5利用canvas绘画二级树形结构图的示例
2017/09/27 HTML / CSS
Zavvi西班牙:电子游戏、极客服装、Blu-ray、Funko Pop等
2019/05/03 全球购物
内科护士实习自我鉴定
2013/10/17 职场文书
小学教研工作制度
2014/01/15 职场文书
宿舍违规用电检讨书
2014/02/16 职场文书
满月酒主持词
2014/03/27 职场文书
2015年依法行政工作总结
2015/04/29 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
python 闭包函数详细介绍
2022/04/19 Python