diff --git a/features/gc.xml b/features/gc.xml index d5945a4e51..6faea61d46 100644 --- a/features/gc.xml +++ b/features/gc.xml @@ -29,46 +29,52 @@ A zval container is created when a new variable is created with a constant value, such as: - + + Creating a new zval container + ]]> - + + - In this case, the new symbol name, "a", is created in the current scope, - and a new variable container is created with type "string", value "new - string". The "is_ref" bit is by default set to "false" because no - user-land reference has been created. The "refcount" is set to "1" as + In this case, the new symbol name, a, is created in the current scope, + and a new variable container is created with the type string and the value + new string. The "is_ref" bit is by default set to &false; because no + user-land reference has been created. The "refcount" is set to 1 as there is only one symbol that makes use of this variable container. Note - that if "refcount" is "1", "is_ref" is always "false". If you have 1, "is_ref" is always &false;. If you have Xdebug installed, you can display this - information by calling: + information by calling xdebug_debug_zval. - + + Displaying zval information + ]]> - - - - which displays: - - - + + &example.outputs; + + +]]> + + - Assigning this variable to another variable name increases the refcount: + Assigning this variable to another variable name will increase the refcount. - + + Increasing refcount of a zval + ]]> - - - - which displays: - - - + + &example.outputs; + + +]]> + + - The refcount is "2" here, because the same variable container is linked - with both "a" and "b". PHP is smart enough not to copy the actual variable + The refcount is 2 here, because the same variable container is linked + with both a and b. + PHP is smart enough not to copy the actual variable container when it is not necessary. Variable containers get destroyed when the "refcount" reaches zero. The "refcount" gets decreased by one when any symbol linked to the variable container leaves the scope (e.g. when the @@ -96,7 +102,9 @@ a: (refcount=2, is_ref=0)='new string' The following example shows this: - + + Decreasing zval refcount + ]]> - - - - which displays: - - - + + &example.outputs; + + +]]> + + - If we now call "unset( $a );", the variable container, including the type + If we now call unset($a);, the variable container, including the type and value, will be removed from memory. @@ -126,49 +133,51 @@ a: (refcount=1, is_ref=0)='new string' Compound Types - Things get a tad more complex with compound types such as arrays and - objects. Instead of a scalar value, arrays and objects store their + Things get a tad more complex with compound types such as arrays and + objects. Instead of a scalar value, arrays + and objects store their properties in a symbol table of their own. This means that the following example creates three zval containers: - + + Creating a <type>array</type> zval + 'life', 'number' => 42 ); xdebug_debug_zval( 'a' ); ?> ]]> - - - - which displays (after formatting): - - - + + &example.outputs.similar; + + (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42 ) - +]]> + + Or graphically + + Zvals for a simple array + + + + + - Or graphically: - - Zvals for a simple array - - - - - - - The three zval containers are: "a", "meaning", and "number". Similar rules - apply for increasing and decreasing "refcounts". Below, we add another + The three zval containers are: a, meaning, and number. + Similar rules apply for increasing and decreasing "refcounts". Below, we add another element to the array, and set its value to the contents of an already existing element: - + + Adding already existing element to an array + 'life', 'number' => 42 ); @@ -176,32 +185,30 @@ $a['life'] = $a['meaning']; xdebug_debug_zval( 'a' ); ?> ]]> - - - - which displays (after formatting): - - - + + &example.outputs.similar; + + (refcount=2, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42, 'life' => (refcount=2, is_ref=0)='life' ) - - - - Or graphically: - - Zvals for a simple array with a reference - - - - +]]> + + Or graphically + + Zvals for a simple array with a reference + + + + + From the above Xdebug output, we see that both the old and new array - element now point to a zval container whose "refcount" is "2". Of course, + element now point to a zval container whose "refcount" is + 2. Of course, there are now two zval containers, but they are the same one. The xdebug_debug_zval function does not show this, but you could see this by also displaying the memory pointer. Removing an @@ -211,7 +218,9 @@ a: (refcount=1, is_ref=0)=array ( container is removed from memory. Again, an example to show this: - + + Removing an element from an array + 'life', 'number' => 42 ); @@ -220,25 +229,26 @@ unset( $a['meaning'], $a['number'] ); xdebug_debug_zval( 'a' ); ?> ]]> - - - - which displays (after formatting): - - - + + &example.outputs.similar; + + (refcount=1, is_ref=0)='life' ) - +]]> + + Now, things get interesting if we add the array itself as an element of - the array, which we do in the next example, in which I also snuck in a + the array, which we do in the next example, in which we also sneak in a reference operator, since otherwise PHP would create a copy: - + + Adding the array itself as an element of it self + ]]> - - - - which displays (after formatting): - - - + + &example.outputs.similar; + + (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=... ) - +]]> + + Or graphically + + Zvals for an array with a circular reference + + + + + - Or graphically: - - Zvals for an array with a circular reference - - - - - - - You can see that the array variable ("a") as well as the second element - ("1") now point to a variable container that has a "refcount" of "2". The + You can see that the array variable (a) as well as the second element + (1) now point to a variable container that has a "refcount" of 2. The "..." in the display above shows that there is recursion involved, which, of course, in this case means that the "..." points back to the original array. @@ -278,26 +285,29 @@ a: (refcount=2, is_ref=1)=array ( Just like before, unsetting a variable removes the symbol, and the reference count of the variable container it points to is decreased by - one. So, if we unset variable $a after running the above code, the - reference count of the variable container that $a and element "1" point to + one. So, if we unset variable $a after running the above code, the + reference count of the variable container that $a and element "1" point to gets decreased by one, from "2" to "1". This can be represented as: - + + Unsetting <varname>$a</varname> + + (refcount=1, is_ref=0)='one', 1 => (refcount=1, is_ref=1)=... ) - - - - Or graphically: - - Zvals after removal of array with a circular reference demonstrating the memory leak - - - - +]]> + + Or graphically + + Zvals after removal of array with a circular reference demonstrating the memory leak + + + + +