background image

PHP

基础 PHP 的引用计数机制

本文是对 PHP 中的引用计数机制进行详细的分析介绍,需要的朋友参考下

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