深入解析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 相关文章推荐
BBS(php & mysql)完整版(七)
Oct 09 PHP
给php新手谈谈我的学习心得
Feb 25 PHP
php自定义函数call_user_func和call_user_func_array详解
Jul 14 PHP
php中计算程序运行时间的类代码
Nov 03 PHP
检查用户名是否已在mysql中存在的php写法
Jan 20 PHP
PHP的魔术常量__METHOD__简介
Jul 08 PHP
thinkphp中html:list标签传递多个参数实例
Oct 30 PHP
php判断文件上传类型及过滤不安全数据的方法
Dec 17 PHP
PHP中使用BigMap实例
Mar 30 PHP
PHP的PDO常用类库实例分析
Apr 07 PHP
php使用Jpgraph创建折线图效果示例
Feb 15 PHP
PHP大文件分块上传功能实例详解
Jul 22 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
mysq GBKl乱码
2006/11/28 PHP
CI框架源码解读之利用Hook.php文件完成功能扩展的方法
2016/05/18 PHP
为何说PHP引用是个坑,要慎用
2018/04/02 PHP
php use和include区别总结
2019/10/13 PHP
php设计模式之状态模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
jtable列中自定义button示例代码
2013/11/21 Javascript
canvas绘图不清晰的解决方案
2017/02/28 Javascript
JavaScript+Html5实现按钮复制文字到剪切板功能(手机网页兼容)
2017/03/30 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
2017/06/26 Javascript
Vue keep-alive实践总结(推荐)
2017/08/31 Javascript
js通过Date对象实现倒计时动画效果
2017/10/27 Javascript
浅析JS中回调函数及用法
2018/07/25 Javascript
小程序实现列表多个批量倒计时
2021/01/29 Javascript
微信小程序 扭蛋抽奖机css3动画实现详解
2019/07/19 Javascript
[02:17]2016完美“圣”典风云人物:Sccc专访
2016/12/03 DOTA
python发送arp欺骗攻击代码分析
2014/01/16 Python
python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件
2014/08/15 Python
深入浅析python中的多进程、多线程、协程
2016/06/22 Python
python中update的基本使用方法详解
2019/07/17 Python
python3获取当前目录的实现方法
2019/07/29 Python
利用rest framework搭建Django API过程解析
2019/08/31 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
2019/10/17 Python
python正则表达式匹配IP代码实例
2019/12/28 Python
Python实现代码块儿折叠
2020/04/15 Python
Keras实现支持masking的Flatten层代码
2020/06/16 Python
Python爬虫回测股票的实例讲解
2021/01/22 Python
39美元购买一副眼镜或太阳镜:39DollarGlasses.com
2018/06/17 全球购物
校园安全广播稿
2014/02/08 职场文书
就业推荐表自我鉴定
2014/03/21 职场文书
网吧最新创业计划书范文
2014/03/27 职场文书
销售团队激励口号
2014/06/06 职场文书
俄语专业毕业生求职信
2014/07/12 职场文书
2014年宣传思想工作总结
2014/12/10 职场文书
小学英语教学随笔
2015/08/14 职场文书
2016年重阳节慰问信
2015/12/01 职场文书