Javascript a-t-il des fuites de mémoire ? Si oui, comment l’éviter ? Compte tenu du fait que plusieurs personnes m'ont posé des questions similaires récemment, il semble que personne n'ait systématiquement étudié cette partie du contenu. J'ai donc l'intention de partager avec vous certaines informations que j'ai compilées il y a quelques années.
Tout d’abord, on peut affirmer avec certitude que certaines manières d’écrire du JavaScript provoqueront des fuites de mémoire, du moins sous IE6. Par conséquent, aujourd'hui, lorsque IE6 refuse de prendre sa retraite, nous devons encore comprendre les connaissances pertinentes (même si dans la plupart des cas, la fuite de mémoire causée par js n'est pas la principale raison du ralentissement de l'ordinateur). Les recherches pertinentes se concentrent principalement sur les années 2005-07. Cet article n'apporte aucune idée nouvelle. Si vous avez des amis qui l'ont étudié à l'époque, vous pouvez simplement l'ignorer.
En tant que développeur front-end, pour comprendre ces problèmes, vous devez savoir de quoi il s'agit et pourquoi. Par conséquent, avant d'introduire les fuites de mémoire js, commençons par pourquoi il y a des fuites de mémoire.
Lorsqu’on parle de fuites de mémoire, il faut parler de la manière dont la mémoire est allouée. Il existe trois manières d'allouer de la mémoire, à savoir :
1. Allocation statique : forme d'allocation de variables statiques et de variables globales. Si nous considérons une pièce comme un programme, nous pouvons considérer la mémoire allouée statiquement comme un mobilier durable dans la pièce. Habituellement, ils n’ont pas besoin d’être libérés et recyclés, car personne ne jette chaque jour les armoires par la fenêtre comme détritus.
2. Allocation automatique : méthode d'allocation de mémoire pour les variables locales sur la pile. La mémoire dans la pile peut être automatiquement libérée avec l'opération pop à la sortie du bloc de code.
C'est similaire aux personnes qui viennent dans une pièce pour faire des choses. Une fois les choses terminées, elles partiront d'elles-mêmes, et l'espace qu'elles occupent sera automatiquement libéré au fur et à mesure que ces personnes partiront.
3. Allocation dynamique : méthode d'allocation dynamique d'espace mémoire dans le tas pour stocker les données. C'est-à-dire que la mémoire utilisée pour utiliser malloc ou new lorsque le programme est en cours d'exécution, nous devons la libérer nous-mêmes en utilisant free ou delete. La durée de vie de la mémoire dynamique est déterminée par le programmeur. Une fois que vous oubliez de le libérer, cela provoquera inévitablement une fuite de mémoire. Dans ce cas, les blocs de mémoire dans le tas sont comme les serviettes que nous utilisons tous les jours. Après les avoir utilisées, nous devons les jeter à la poubelle, sinon la maison sera en désordre. Les paresseux rêvent donc d’avoir un robot ménager pour faire le ménage avec eux. Dans le développement de logiciels, si vous êtes trop paresseux pour libérer de la mémoire, vous avez également besoin d'un robot similaire - qui est en fait un ramasse-miettes implémenté par un algorithme spécifique. Ce sont précisément certains défauts du mécanisme de récupération de place lui-même qui entraînent des fuites de mémoire JavaScript.
Il y a quelques années, j'ai lu un article intitulé « Une histoire intéressante du recyclage des déchets », qui donnait une explication approfondie du mécanisme de collecte des déchets.
Tout comme la suralimentation, une technologie utilisée par de nombreuses voitures de luxe comme argument de vente et qui a été utilisée par Mercedes-Benz dans les années 1910, la technologie de recyclage des déchets existe depuis longtemps. Le langage Lisp, né au MIT vers 1960, a été le premier langage qui s'appuyait fortement sur la technologie d'allocation dynamique de mémoire. Presque toutes les données en Lisp apparaissent sous la forme de « tables », et l'espace occupé par les « tables » est dans le tas. alloués dynamiquement. La fonctionnalité innée de gestion dynamique de la mémoire du langage Lisp nécessite que les concepteurs du langage Lisp résolvent le problème de la libération automatique de chaque bloc de mémoire dans le tas (sinon, les programmeurs Lisp seront inévitablement submergés par d'innombrables instructions free ou delete dans le programme) Cela a directement conduit à la naissance et au développement de la technologie de collecte des déchets.
Les trois algorithmes de récupération de place les plus élémentaires sont également apparus ensemble à cette époque. Jetons-les un par un :
Algorithme de comptage de références : c'est peut-être la première méthode qui vient à l'esprit. Au sens figuré, le comptage de références peut être compris de cette façon. Il y a beaucoup de livres blancs dans la maison, et ces papiers sont comme des souvenirs. Utiliser la mémoire, c’est comme écrire sur ces morceaux de papier. La mémoire peut être utilisée à volonté, mais il y a une condition : quiconque utilise un morceau de papier doit écrire un compte de 1 sur le coin du papier. Si deux personnes utilisent un morceau de papier en même temps, le compte devient. 2, et ainsi de suite. Lorsqu'une personne finit d'utiliser un morceau de papier, le décompte sur le coin doit être décrémenté de 1. De cette façon, une fois que le décompte devient 0, les conditions de collecte des déchets sont remplies et le robot qui attend à l'écart jettera immédiatement le papier dans le boîte à ordures. Le garbage collector basé sur un compteur de référence s'exécute plus rapidement, n'interrompt pas l'exécution du programme pendant une longue période et convient aux programmes qui doivent s'exécuter en temps réel. Cependant, le compteur de référence augmente la surcharge d'exécution du programme ; en même temps, il existe un autre problème majeur. Cet algorithme a un défaut, c'est-à-dire qu'une fois qu'une référence circulaire est générée, la mémoire sera perdue. Par exemple, nous créons deux objets a et b. À ce moment, les comptes de a et b sont tous deux égaux à 1. Ensuite, nous pointons un attribut de a vers b et un attribut de b vers a. Dans la relation de référence, les comptes de a et b deviennent tous deux 2. Lorsque le programme se termine et quitte la portée, le programme décrémente automatiquement le compte de a de 1. Puisque le compte de a à la fin est toujours 1, a ne sera pas libéré De même, le décompte final de b est également 1, b ne sera pas libéré et la mémoire est simplement divulguée !