Home > Article > Backend Development > In-depth analysis of how PHP garbage collection mechanism handles memory leaks_PHP Tutorial
We talked about refcount and is_ref last time, let’s talk about memory leaks here
$a = array(1, 2, &$a);
unset($a);
In older PHP versions, this will appear here Memory leak, analysis is as follows:
Execute the first line, you can know that the zval pointed to by $a and $a[2] refcount=2, is_ref=1
Then execute the second line. $a will be deleted from the symbol table and points to the refcount-- of zval. At this time, refcount=1, because refcount!=0, so zval will not be regarded as Garbage collection, but at this time we lost the entry of $a[2] pointing to this zval, so this zval became a piece of memory garbage
The same thing can happen in class internal references, such as
$a = new Man();
$a->self = &$a;
unset($a);
So how to solve this problem, new The GC mechanism uses an algorithm to solve this problem
PHP has a root buffer to store zval node information. When the root buffer is full or the gc function is called manually, the GC algorithm starts
For a zval of array or class type, when the garbage collection mechanism starts, the algorithm will traverse the zval of the elements/members inside the zval array/class and decrement the refcount by 1. If If the refcount of the zval is reduced to 0 after the traversal is completed, it means that the zval is a memory garbage and will be destroyed. See the example below
$a = array(1, 2, &$a, &$a);
unset($a);
Easy Knowing the zval pointed to by $a, assume that the refcount of z1=3, is_ref=1
When unset($a) is executed, $a has been deleted from the symbol table, and we have also lost the access to z1. At this time, z1 refcount=2, is_ref=1
When GC starts, the refcount of zval of the array element of z1 will be traversed and subtracted by 1. When traversing to a[2], z1 refcount--, when a[3], z1 refcount--, At this time, z1 refcount = 0, z1 can be marked as memory garbage, and it will be recycled after the algorithm
In summary, it can be expressed like this: If there is an array type zval, its element zval is traversed once, and the refcount of the traversed zval-- is used. If the final zval with refcount=0 is garbage, , need to be recycled