Instructions de mise en œuvre
1. Ajoutez un compteur de référence à l'objet. La valeur du compteur de référence augmentera à chaque fois quelque part. Chaque fois qu'une référence devient invalide, le compteur est décrémenté de un.
Si le refcount de la valeur de la variable est réduit de un et est égal à 0, la valeur sera libérée et ne sera pas une poubelle. Le ramasse-miettes ne s’en occupe pas.
Si le refcount de la valeur de la variable est supérieur à 0 après avoir été réduit de un, la valeur est considérée comme non libérable et peut devenir un déchet.
2. Le garbage collector collecte les éventuels déchets. Après avoir atteint une certaine quantité, il démarre le programme d'identification des déchets et libère les vrais déchets.
Exemple
<?php // Cas du mécanisme de garbage collection PHP : reportez-vous au manuel php //----------------------------------Type scalaire----------------------------------- // astuce : Chaque variable PHP existe dans un conteneur de variables appelé "zval", qui contient le type et la valeur de la variable, "is_ref" : s'il s'agit d'une variable de référence, "refcount" : nombre de références // ex : Générer un nouveau conteneur zval $a = 'new string'; // ex : afficher les informations du conteneur zval xdebug_debug_zval('a'); // a : (refcount=1, is_ref=0),string 'new string' (length=10) // ex : Augmente le nombre de références du conteneur zval $c = $b = $a; xdebug_debug_zval('a'); // a:(refcount=3, is_ref=0),string 'nouvelle chaîne' (longueur=10) xdebug_debug_zval('b'); // b:(refcount=3, is_ref=0),string 'nouvelle chaîne' (longueur=10) xdebug_debug_zval('c'); // c:(refcount=3, is_ref=0),string 'nouvelle chaîne' (longueur=10) // Astuce : Il n'y a qu'un seul conteneur pour le moment, car PHP ne copiera pas le conteneur de variables généré lorsque cela n'est pas nécessaire // A ce moment, ce conteneur de variables est associé à la variable a, à la variable b et à la variable c. unset($b); // ex : réduire le nombre de références xdebug_debug_zval('a'); // a:(refcount=2, is_ref=0),string 'nouvelle chaîne' (longueur=10) // astuce : unset Lors de la suppression d'une variable, le nombre de variables refcount est décrémenté de un. À ce stade, seuls $a et $b pointent vers le conteneur de variables. non défini($a); non défini($c); var_dump($a); // Astuce : A ce moment, le recount est 0 et la variable est supprimée // Lorsque le recount devient 0, le conteneur de variable contenant le type et la valeur sera supprimé de la mémoire. //------------------------Type composite------------- echo '--------------Type composite------------<br/>'; $a = tableau( 'nom' => 'junior', 'âge' => 18 ); xdebug_debug_zval('a'); // a:(refcount=1, is_ref=0), // tableau (taille=2) // 'nom' => (refcount=1, is_ref=0), chaîne 'junior' (longueur=6) // 'âge' => (refcount=1, is_ref=0),int 18 // ex : Ajouter un élément existant au tableau $a['love'] = $a['name']; xdebug_debug_zval('a'); // a:(refcount=1, is_ref=0), // tableau (taille=3) // 'nom' => (refcount=2, is_ref=0), chaîne 'junior' (longueur=6) // 'âge' => (refcount=1, is_ref=0),int 18 // 'love' => (refcount=2, is_ref=0),string 'junior' (longueur=6) // $a = array('un'); // xdebug_debug_zval('a'); // // $b = &$a; // $c = $a ; // $b = &$c; // xdebug_debug_zval('b'); // xdebug_debug_zval('c'); // xdebug_debug_zval('a'); // Nettoyer le problème du conteneur de variables echo '------------Problème de fuite de mémoire----------<br/>'; $a = array('un'); xdebug_debug_zval('a'); // a:(refcount=1, is_ref=0), // tableau (taille=1) // 0 => (refcount=1, is_ref=0), chaîne 'one' (longueur=3) $a[] = &$a; xdebug_debug_zval('a'); // a:(refcount=2, is_ref=1), // tableau (taille=2) // 0 => (refcount=1, is_ref=0), chaîne 'one' (longueur=3) // 1 => (refcount=2, is_ref=1), // &tableau // non défini($a); // (refcount=1, is_ref=1)=tableau ( // 0 => (refcount=1, is_ref=0)='un', // 1 => (refcount=1, is_ref=1)=... // ) // astuce : Après unset($a), le nombre de références est décrémenté de un, même s'il n'y a plus de symbole dans une portée pointant vers cette structure (c'est-à-dire le conteneur de variables), // Puisque l'élément de tableau "1" pointe toujours vers le tableau lui-même, ce conteneur ne peut pas être effacé // Puisqu'il n'y a aucun autre symbole pointant vers lui, l'utilisateur n'a aucun moyen d'effacer cette structure, ce qui entraîne une fuite de mémoire // Heureusement , PHP va Cette structure de données est effacée à la fin de l'exécution du script, mais beaucoup de mémoire sera consommée avant que PHP ne l'efface. // La même chose se produit avec les objets, en fait, cela est plus susceptible de se produire avec les objets car les objets sont toujours implicitement référencés.
Ce qui précède explique comment le comptage de références PHP implémente le garbage collection. J'espère que cela sera utile à tout le monde.