深入解析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 error_log 函数的使用
Apr 13 PHP
php写的简易聊天室代码
Jun 04 PHP
深入理解curl类,可用于模拟get,post和curl下载
Jun 08 PHP
php抓取页面的几种方法详解
Jun 17 PHP
分享下php5类中三种数据类型的区别
Jan 26 PHP
PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
Mar 10 PHP
PHP中你应该知道的require()文件包含的正确用法
Jun 12 PHP
twig模板常用语句实例小结
Feb 04 PHP
PHP7新特性foreach 修改示例介绍
Aug 26 PHP
swoole和websocket简单聊天室开发
Nov 18 PHP
PHP中localeconv()函数的用法
Mar 26 PHP
Laravel框架实现文件上传的方法分析
Sep 29 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变量修饰符static的使用
2013/06/28 PHP
php环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
jQuery判断checkbox(复选框)是否被选中以及全选、反选实现代码
2014/02/21 Javascript
JavaScript实现继承的4种方法总结
2014/10/16 Javascript
JavaScript必知必会(三) String .的方法来自何方
2016/06/08 Javascript
jquery.zclip轻量级复制失效问题
2017/01/08 Javascript
无循环 JavaScript(map、reduce、filter和find)
2017/04/08 Javascript
Nodejs搭建wss服务器教程
2017/05/24 NodeJs
JavaScript面向对象精要(上部)
2017/09/12 Javascript
浅谈Vue网络请求之interceptors实际应用
2018/02/28 Javascript
p5.js入门教程之鼠标交互的示例
2018/03/16 Javascript
React中的render何时执行过程
2018/04/13 Javascript
JavaScript new对象的四个过程实例浅析
2018/07/31 Javascript
vue打包之后生成一个配置文件修改接口的方法
2018/12/09 Javascript
JavaScript实现PC端横向轮播图
2020/02/07 Javascript
[00:53]TI3正赛第三天 DK怒破A队不败金身 现场国旗飘扬热血激昂
2013/08/10 DOTA
[22:20]初生之犊-TI4第5名LGD战队纪录片
2014/08/13 DOTA
[05:11]TI9战队采访——VIRTUSPRO
2019/08/22 DOTA
深入理解Python中的*重复运算符
2017/10/28 Python
PyTorch学习:动态图和静态图的例子
2020/01/06 Python
教你使用Sublime text3搭建Python开发环境及常用插件安装另分享Sublime text3最新激活注册码
2020/11/12 Python
详解css3 Transition属性(平滑过渡菜单栏案例)
2017/09/05 HTML / CSS
HTML5适合的情人节礼物有纪念日期功能
2021/01/25 HTML / CSS
机械专业毕业生自荐信
2013/11/02 职场文书
营业员实习自我鉴定
2013/12/07 职场文书
小学新教师培训方案
2014/02/03 职场文书
中介业务员岗位职责
2014/04/09 职场文书
感谢信模板大全
2015/01/23 职场文书
MySQL 分页查询的优化技巧
2021/05/12 MySQL
详解CSS不定宽溢出文本适配滚动
2021/05/24 HTML / CSS
详解redis在微服务领域的贡献
2021/10/16 Redis
SQL 聚合、分组和排序
2021/11/11 MySQL
Python中with上下文管理协议的作用及用法
2022/03/18 Python
避坑之 JavaScript 中的toFixed()和正则表达式
2022/04/19 Javascript