深入解析PHP的引用计数机制


Posted in PHP onJune 14, 2013

PHP的变量声明并赋值后,变量名存在符号表中,而值和类信息存在zval中,zval中包含四个变量,is_ref,refcount,value,type,zval源码如下

struct _zval_struct {  
    /* Variable information */  
    zvalue_value value;     /* value */  
    zend_uint refcount__gc;  
    zend_uchar type;    /* active type */  
    zend_uchar is_ref__gc;  
};

refcount表示value地址与其相同的zval共有多少个,refcount=0时,zval被销毁
is_ref表示一个zval是否被引用,有“0”和“1”两种状态

此处分析一下什么时候zval会被复制或者开辟新的内存空间呢
1.当is_ref=0,且refcount>1时,如果改变某个指向该zval的变量的值,会生成新zval,原zval的refcount--,例如:$a=1;$b=$a;$b=2;,zval将被复制,也就是说原先ab指向同一个zval,后来b会使用新开辟的zval

2.当is_ref=0,且refcount>1时,如果将zval赋值给某个引用变量,那么用来赋值和变量和被赋值的变量会使用同一个原zval,而其他指向原zval的变量将会指向一个新复制的zval,且refcount会被重新计算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此时ad使用原zval,bc使用新复制出来的zval

3.当is_ref=1,且refcount>1时,如果将zval复制给某个非引用变量,该非引用变量会使用一个新复制的zval,元zval的refcount不变,例如:$a=1;$b=&$a;$c=$a,那么ab使用原zval,而c使用新复制的zval
type表示该zval的值类型,宏定义如下

#define IS_NULL     0  
#define IS_LONG     1  
#define IS_DOUBLE   2  
#define IS_BOOL     3  
#define IS_ARRAY    4  
#define IS_OBJECT   5  
#define IS_STRING   6  
#define IS_RESOURCE 7  
#define IS_CONSTANT 8  
#define IS_CONSTANT_ARRAY   9

value表示该zval的值,他也是个共同体,代码如下
typedef union _zvalue_value {  
    long lval;                  /* long value */  
    double dval;                /* double value */  
    struct {  
        char *val;  
        int len;  
    } str;  
    HashTable *ht;              /* hash table value */  
    zend_object_value obj;  
} zvalue_value;

现在你知道php是如何类型变换的了,因为他的值存的其实是个可以代表任何类型的结构体,而具体的取值则根据type来决定是用共同体里的哪个变量来存值的

见下面的例子1

.-----------
$a = 1;
$b = $a;
$c = $a;
.-----------
$d = &$a;
.-----------
$a = 2;
.-----------
$b = null;

查看refcount,is_ref,zval的变化
执行完第一部分后来看看输出
1-----------------------------
a:(refcount=3, is_ref=0),int 1
b:(refcount=3, is_ref=0),int 1
c:(refcount=3, is_ref=0),int 1
可以看出来a,b,c使用同一个zval
再看执行完第二部分的
2----------------------------
a:(refcount=2, is_ref=1),int 1
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 1
注意此时a,d在一起了,他们使用同一个zval,而bc使用一个新生成的zval,同时重新计算两个zval的refcount和is_ref
3----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
可以知道ad这两个is_ref=1的好基友的值是同时改变的
4----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=1, is_ref=0),null
c:(refcount=1, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
bc由于他们的zval的is_ref=0,所以他们不是好基友,他们的值不会同时改变,于是bc的zval再次分裂,b = null c = 1
PHP 相关文章推荐
小偷PHP+Html+缓存
Dec 20 PHP
php db类库进行数据库操作
Mar 19 PHP
自定义session存储机制避免会话保持问题
Oct 08 PHP
php通过session防url攻击方法
Dec 10 PHP
php查询mssql出现乱码的解决方法
Dec 29 PHP
php实现遍历多维数组的方法
Nov 25 PHP
php实现批量删除挂马文件及批量替换页面内容完整实例
Jul 08 PHP
php版微信支付api.mch.weixin.qq.com域名解析慢原因与解决方法
Oct 12 PHP
PHP常用的三种设计模式
Feb 17 PHP
Yii2框架实现登录、退出及自动登录功能的方法详解
Oct 24 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
php根据命令行参数生成配置文件详解
Mar 15 PHP
深入解析PHP垃圾回收机制对内存泄露的处理
Jun 14 #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
You might like
MySql 按时间段查询数据方法(实例说明)
2008/11/02 PHP
解析左右值无限分类的实现算法
2013/06/20 PHP
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
将光标定位于输入框最右侧实现代码
2012/12/04 Javascript
Javascript 中 null、NaN和undefined的区别总结
2013/04/10 Javascript
JS替换文本域内的回车示例
2014/02/18 Javascript
jQuery截取指定长度字符串代码
2014/08/21 Javascript
JavaScript实现三阶幻方算法谜题解答
2014/12/29 Javascript
Lab.js初次使用笔记
2015/02/28 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
js实现tab切换效果实例
2015/09/16 Javascript
javascript制作照片墙及制作过程中出现的问题
2016/04/04 Javascript
Angular表单验证实例详解
2016/10/20 Javascript
小程序指纹验证的实现代码
2018/12/04 Javascript
vue-router beforeEach跳转路由验证用户登录状态
2018/12/26 Javascript
微信小程序实现传递多个参数与事件处理
2019/08/12 Javascript
js实现百度淘宝搜索功能
2020/02/17 Javascript
electron踩坑之dialog中的callback解决
2020/10/06 Javascript
使用webpack5从0到1搭建一个react项目的实现步骤
2020/12/16 Javascript
[00:47]DOTA2荣耀之路6:玩不了啦!
2018/05/30 DOTA
Python书单 不将就
2017/07/11 Python
Python socket实现的简单通信功能示例
2018/08/21 Python
Python常用特殊方法实例总结
2019/03/22 Python
python实现控制电脑鼠标和键盘,登录QQ的方法示例
2019/07/06 Python
关于python字符串方法分类详解
2019/08/20 Python
新年福利来一波之Python轻松集齐五福(demo)
2020/01/20 Python
django实现日志按日期分割
2020/05/21 Python
详解HTML5 录音的踩坑之旅
2017/12/26 HTML / CSS
如何给HTML标签中的文本设置修饰线
2019/11/18 HTML / CSS
Artist Guitars新西兰:乐器在线商店
2017/09/17 全球购物
师范生实习自我鉴定
2013/11/01 职场文书
公关关系专员的自我评价分享
2013/11/20 职场文书
企业厂长岗位职责
2013/12/17 职场文书
酒店管理失职检讨书
2014/09/16 职场文书
五年级语文教学反思
2016/03/03 职场文书
Python机器学习之决策树和随机森林
2021/07/15 Javascript