Deeply parse the reference counting mechanism of PHP. After the PHP variable is declared and assigned a value, the variable name exists in the symbol table, and the value and class information exist in zval. zval contains four variables: is_ref, refcount, value, type, the zval source code is as follows: Copy the PHP variable declaration and assign values. the variable name exists in the symbol table, and the value and class information exist in zval. zval 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
Struct, is_ref, refcount, value, type, zval source code is as follows...