深入解析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加密解密的代码
Oct 09 PHP
PHP扩展编写点滴 技巧收集
Mar 09 PHP
PHP自定义函数收代码
Aug 01 PHP
php根据身份证号码计算年龄的实例代码
Jan 18 PHP
从零开始学YII2框架(四)扩展插件yii2-kartikgii
Aug 20 PHP
PHP文件读取功能的应用实例
May 08 PHP
PHP curl模拟登录带验证码的网站
Nov 30 PHP
php魔术方法功能与用法实例分析
Oct 19 PHP
PHP解耦的三重境界(浅谈服务容器)
Mar 13 PHP
Laravel使用消息队列需要注意的一些问题
Dec 13 PHP
PHP 布尔值的自增与自减的实现方法
May 03 PHP
PHP+swoole+linux实现系统监控和性能优化操作示例
Apr 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
10个可以简化php开发过程的MySQL工具
2010/04/11 PHP
PHP批量生成静态HTML的简单原理和方法
2014/04/20 PHP
PHP获取音频文件的相关信息
2015/06/22 PHP
PHP解耦的三重境界(浅谈服务容器)
2017/03/13 PHP
php新建文件的方法实例
2019/09/26 PHP
JavaScript 事件冒泡简介及应用
2010/01/11 Javascript
让你的CSS像Jquery一样做筛选的实现方法
2011/07/10 Javascript
javascript之querySelector和querySelectorAll使用说明
2011/10/09 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
Form表单上传文件(type="file")的使用
2017/08/03 Javascript
基于javascript中的typeof和类型判断(详解)
2017/10/27 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
2017/12/14 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
微信小程序实现评论功能
2018/11/28 Javascript
页面内锚点定位及跳转方法总结(推荐)
2019/04/24 Javascript
详解微信小程序的不同函数调用的几种方法
2019/05/08 Javascript
vue3.0生命周期的示例代码
2020/09/24 Javascript
[02:12]2015国际邀请赛 SHOWOPEN
2015/08/05 DOTA
介绍Python中的__future__模块
2015/04/27 Python
深入理解python多进程编程
2016/06/12 Python
python爬虫之模拟登陆csdn的实例代码
2018/05/18 Python
python中使用print输出中文的方法
2018/07/16 Python
Python 实用技巧之利用Shell通配符做字符串匹配
2019/08/23 Python
解析Python3中的Import
2019/10/13 Python
关于Keras模型可视化教程及关键问题的解决
2020/01/24 Python
python基于socket函数实现端口扫描
2020/05/28 Python
Bose美国官网:购买Bose耳机和音箱
2019/03/10 全球购物
学生实习自我鉴定
2013/10/11 职场文书
个人实用简单的自我评价
2013/10/19 职场文书
外贸英语毕业生自荐信
2013/11/14 职场文书
接待员岗位责任制
2014/02/10 职场文书
遗产继承公证书
2014/04/09 职场文书
公司请假条范文
2014/04/11 职场文书
小学生推普周国旗下讲话稿
2014/09/21 职场文书
大学生军训心得体会5篇
2019/08/15 职场文书