深入解析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实现WEB动态网页静态
Oct 09 PHP
PHP时间戳使用实例代码
Jun 07 PHP
Joomla下利用configuration.php存储简单数据
May 19 PHP
smarty模板嵌套之include与fetch性能测试
Dec 05 PHP
discuz程序的PHP加密函数原理分析
Aug 05 PHP
使用PHP遍历文件目录与清除目录中文件的实现详解
Jun 24 PHP
php单文件版在线代码编辑器
Mar 12 PHP
Yii实现简单分页的方法
Apr 29 PHP
thinkPHP中钩子的使用方法实例分析
Nov 16 PHP
使用PHPUnit进行单元测试并生成代码覆盖率报告的方法
Mar 08 PHP
PHP示例演示发送邮件给某个邮箱
Apr 03 PHP
php计数排序算法的实现代码(附四个实例代码)
Mar 31 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
php读取二进制流(C语言结构体struct数据文件)的深入解析
2013/06/13 PHP
jquery+php+ajax显示上传进度的多图片上传并生成缩略图代码
2014/10/15 PHP
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
使用Js让Html中特殊字符不被转义
2013/11/05 Javascript
JS、jquery实现几分钟前、几小时前、几天前等时间差显示效果的代码实例分享
2014/04/11 Javascript
分享9个最好用的JavaScript开发工具和代码编辑器
2015/03/24 Javascript
D3.js中data(), enter() 和 exit()的问题详解
2015/08/17 Javascript
Webpack 实现 AngularJS 的延迟加载
2016/03/02 Javascript
ES6中非常实用的新特性介绍
2016/03/10 Javascript
基于JavaScript实现在新的tab页打开url
2016/08/04 Javascript
深入浅析Vue组件开发
2016/11/25 Javascript
jQuery中的deferred使用方法
2017/03/27 jQuery
vue.js单页面应用实例的简单实现
2017/04/10 Javascript
angular实现IM聊天图片发送实例
2017/05/08 Javascript
jQuery实现下拉菜单的实例代码
2017/06/19 jQuery
Nodejs 复制文件/文件夹的方法
2017/08/24 NodeJs
JavaScript模块模式实例详解
2017/10/25 Javascript
Bootstrap实现下拉菜单多级联动
2017/11/23 Javascript
jquery 验证用户名是否重复代码实例
2019/05/14 jQuery
webpack4 SplitChunks实现代码分隔详解
2019/05/23 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
Javascript实现鼠标移入方向感知
2020/06/24 Javascript
酷! 程序员用Python带你玩转冲顶大会
2018/01/17 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
django框架自定义用户表操作示例
2018/08/07 Python
使用Python三角函数公式计算三角形的夹角案例
2020/04/15 Python
Python如何合并多个字典或映射
2020/07/24 Python
Yahoo的PHP面试题
2014/05/26 面试题
品学兼优的大学生自我评价
2013/09/20 职场文书
拾金不昧表扬信范文
2014/01/11 职场文书
3.12植树节活动总结2014
2014/03/13 职场文书
学生自我评语大全
2014/04/18 职场文书
2014年办公室个人工作总结
2014/11/12 职场文书
九华山导游词
2015/02/03 职场文书
2019年农民幸福观调查的实践感悟
2019/12/19 职场文书
python分分钟绘制精美地图海报
2022/02/15 Python