深入解析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制作静态网站的模板框架(三)
Oct 09 PHP
php 仿Comsenz安装效果代码打包提供下载
May 09 PHP
深入理解PHP原理之错误抑制与内嵌HTML分析
May 02 PHP
php生成txt文件标题及内容的方法
Jan 16 PHP
PHP获取网页标题的3种实现方法代码实例
Apr 11 PHP
php实现redis数据库指定库号迁移的方法
Jan 14 PHP
隐藏Nginx或Apache以及PHP的版本号的方法
Jan 03 PHP
php使用curl代理实现抓取数据的方法
Feb 03 PHP
通过php动态传数据到highcharts
Apr 05 PHP
php中的explode()函数实例介绍
Jan 18 PHP
php5.3/5.4/5.5/5.6/7常见新增特性汇总整理
Feb 27 PHP
如何在PHP环境中使用ProtoBuf数据格式
Jun 19 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写的求多项式导数的函数代码
2012/07/04 PHP
深入php函数file_get_contents超时处理的方法详解
2013/06/03 PHP
PHP register_shutdown_function函数的深入解析
2013/06/03 PHP
PHP自定义大小验证码的方法详解
2013/06/07 PHP
php另类上传图片的方法(PHP用Socket上传图片)
2013/10/30 PHP
推荐10个提供免费PHP脚本下载的网站
2014/12/31 PHP
PHP微信公众号开发之微信红包实现方法分析
2017/07/14 PHP
js中各浏览器中鼠标按键值的差异
2011/04/07 Javascript
js自定义方法通过隐藏iframe实现文件下载
2013/02/21 Javascript
JS实现淘宝幻灯片效果的实现方法
2013/03/22 Javascript
解析jquery中的ajax缓存问题
2013/12/19 Javascript
当jQuery1.7遇上focus方法的问题
2014/01/26 Javascript
js通过location.search来获取页面传来的参数
2014/09/11 Javascript
node.js中的fs.readSync方法使用说明
2014/12/17 Javascript
jQuery实现的网页左侧在线客服效果代码
2015/10/23 Javascript
原生JS+Canvas实现五子棋游戏实例
2017/06/19 Javascript
vue组件父子间通信之综合练习(聊天室)
2017/11/07 Javascript
关于RxJS Subject的学习笔记
2018/12/05 Javascript
js实现无缝轮播图特效
2020/05/09 Javascript
vue-model实现简易计算器
2020/08/17 Javascript
nginx配置域名后的二级目录访问不同项目的配置操作
2020/11/06 Javascript
python re正则表达式模块(Regular Expression)
2014/07/16 Python
python的random模块及加权随机算法的python实现方法
2017/01/04 Python
Python中使用haystack实现django全文检索搜索引擎功能
2017/08/26 Python
Python匿名函数/排序函数/过滤函数/映射函数/递归/二分法
2019/06/05 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
AmazeUI框架搭建的方法步骤(图文)
2020/08/17 HTML / CSS
来自美国主售篮球鞋的零售商店:KICKSUSA
2017/11/28 全球购物
写好自荐信的技巧
2013/11/08 职场文书
土木工程个人自荐信范文
2013/11/30 职场文书
办公室文员工作职责
2014/01/31 职场文书
服装创业计划书范文
2014/02/05 职场文书
海上钢琴师的观后感
2015/06/11 职场文书
python基础学习之递归函数知识总结
2021/05/26 Python
详解Redis集群搭建的三种方式
2021/05/31 Redis
Django rest framework如何自定义用户表
2021/06/09 Python