This article provides a detailed analysis of the reference counting mechanism in PHP. after a friend needs to refer to the PHP variable declaration and assign values, the variable name will exist in the symbol table, the value and class information exist in zval, which contains four variables,
Is_ref, refcount, value, type, zvalThe source code is as follows:
The code is as follows:
Struct _ zval_struct {
/* Variable information */
Zvalue_value value;/* value */
Zend_uint refcount _ gc;
Zend_uchar type;/* active type */
Zend_uchar is_ref _ gc;
};
Refcount indicates the total number of zval with the same value address. when refcount is set to 0, zval is destroyed.
Is_ref indicates whether a zval is referenced. There are two statuses: "0" and "1 ".
Here, we will analyze when zval will be copied or new memory space will be opened.
1. when is_ref = 0 and refcount> 1, if you change the value of a variable pointing to this zval, a new zval, the original zval refcount -- is generated, for example: $ a = 1; $ B = $ a; $ B = 2; zval will be copied, that is, the original AB points to the same zval, and then B will use the newly created zval
2. when is_ref = 0 and refcount> 1, if zval is assigned to a reference variable, the original zval is used to assign values to the variable and to the variable to be assigned, other variables pointing to the original zval point to a newly copied zval, and the refcount is recalculated, for example, $ a = 1; $ B = $; $ c = $ a; $ d = & $ a; in this case, ad uses the original zval and bc uses the newly copied zval.
3. when is_ref = 1 and refcount> 1, if zval is copied to a non-referenced variable, a newly copied zval will be used for this non-referenced variable, and the refcount of zval will not change, for example: $ a = 1; $ B = & $ a; $ c = $ a, AB uses the original zval, and c uses the newly copied zval.
Type indicates the zval value type. the macro definition is as follows:
The code is as follows:
# 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 indicates the zval value. it is also a community and the code is as follows:
The code is as follows:
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;
Now you know how php changes the type, because its value is actually a struct that can represent any type, the specific value depends on the type to determine which variable in the community to store the value.
See example 1 below.
The code is as follows:
.-----------
$ A = 1;
$ B = $;
$ C = $;
.-----------
$ D = & $;
.-----------
$ A = 2;
.-----------
$ B = null;
View refcount, is_ref, and zval changes
After the first part is executed, check the output.
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
We can see that a, B, and c use the same zval.
Then, let's look at
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
Note that at this time a and d are together, they use the same zval, while bc uses a newly generated zval and recalculates the refcount and is_ref of the two zval.
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
We can know that the values of the two is_ref = 1 Friends of ad are changed at the same time.
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 because their zval is_ref = 0, so they are not good friends, their values will not change at the same time, so bc's zval split again, B = null c = 1