深入解析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 相关文章推荐
介绍几个array库的新函数 php
Dec 29 PHP
php调用mysql数据 dbclass类
May 07 PHP
php中CI操作多个数据库的代码
Jul 05 PHP
php正则表达式使用的详细介绍
Apr 27 PHP
php 删除目录下N分钟前创建的所有文件的实现代码
Aug 10 PHP
PHP的pcntl多进程用法实例
Mar 19 PHP
PHP的运行机制与原理(底层)
Nov 16 PHP
Symfony2实现在doctrine中内置数据的方法
Feb 05 PHP
PHP基于单例模式编写PDO类的方法
Sep 13 PHP
PHPCMS忘记后台密码的解决办法
Oct 30 PHP
laravel 查询数据库获取结果实现判断是否为空
Oct 24 PHP
php实现断点续传大文件示例代码
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中通过Ajax如何实现异步文件上传的代码实例
2011/05/07 PHP
php中的filesystem文件系统函数介绍及使用示例
2014/02/13 PHP
Discuz批量替换帖子内容的方法(使用SQL更新数据库)
2014/06/23 PHP
PHP 中TP5 Request 请求对象的实例详解
2017/07/31 PHP
使用composer 安装 laravel框架的方法图文详解
2019/08/02 PHP
php的instanceof和判断闭包Closure操作示例
2020/01/26 PHP
浅谈Javascript嵌套函数及闭包
2010/11/09 Javascript
jquery 扑捉回车键事件代码
2014/04/24 Javascript
javascript学习笔记(七)Ajax和Http状态码
2014/10/08 Javascript
JS中处理时间之setUTCMinutes()方法的使用
2015/06/12 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
jQuery插件dataTables添加序号列的方法
2016/07/06 Javascript
vue.js入门教程之计算属性
2016/09/01 Javascript
AngularJS指令与指令之间的交互功能示例
2016/12/14 Javascript
在Vue-cli里应用Vuex的state和mutations方法
2018/09/16 Javascript
vue使用websocket的方法实例分析
2019/06/22 Javascript
三步实现ionic3点击退出app程序
2019/09/17 Javascript
node读写Excel操作实例分析
2019/11/06 Javascript
Django在win10下的安装并创建工程
2017/11/20 Python
python3.6.3安装图文教程 TensorFlow安装配置方法
2020/06/24 Python
python paramiko利用sftp上传目录到远程的实例
2019/01/03 Python
Python 从一个文件中调用另一个文件的类方法
2019/01/10 Python
NumPy统计函数的实现方法
2020/01/21 Python
Python MySQL 日期时间格式化作为参数的操作
2020/03/02 Python
Django ForeignKey与数据库的FOREIGN KEY约束详解
2020/05/20 Python
Python如何爬取51cto数据并存入MySQL
2020/08/25 Python
MCAKE蛋糕官方网站:一直都是巴黎的味道
2018/02/06 全球购物
The Athlete’s Foot新西兰:新西兰最大的运动鞋零售商
2019/12/23 全球购物
Lungolivigno Fashion官网:高级时装在线购物
2020/10/17 全球购物
Johnson Fitness澳大利亚:高级健身器材
2021/03/16 全球购物
秋季运动会活动方案
2014/02/05 职场文书
绩效考核实施方案
2014/03/18 职场文书
商务考察邀请函模板
2015/02/02 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书
彻底弄懂Python中的回调函数(callback)
2022/06/25 Python
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL