7
votes

Comment Settimeout () crée-t-il une fuite de mémoire dans ce code?

J'examinais les diapositives de cette présentation: http://slid.es/gruizdevilla/memory

Et sur l'une des diapositives, ce code est présenté avec la suggestion qu'il crée une fuite de mémoire: xxx

peut-on expliquer le problème plus en détail ici? Il mera peut-être manquer quelques subtilités ici.


3 commentaires

Évidemment, il y aura une référence à buggyroject pour toujours, mais je ne sais pas si vous appelez une fuite de mémoire dans le sens traditionnel ou non. Ils pourraient impliquer une sorte de cycle puisque la fermeture fait référence au délai d'attente afin que chaque appel créerait théoriquement une nouvelle fermeture à vie longue, sauf que Val est une seule référence.


Cela m'a aussi confus. J'ai envie de me manquer un point important et je ne suis pas sûr que je le suis. Je suppose que le seul point qu'ils fabriquent est le seul point évident que vous aurez un morceau de code indéfiniment et qu'il utilisera suffisamment de mémoire pour qu'il soit exécuté (et qu'il soit en vie, le buggyObject original dans le processus). Mais cela semble super évident. Je pensais qu'ils essayaient de faire un point subtil d'une fuite de croissance exponentielle qui serait créée, mais je ne vois pas comment.


Quelqu'un peut-il donner une version fixe de ce code?


3 Réponses :


5
votes

Il y a Une autre question décrit comment SettimeOut () looks Comme si cela a des fuites de mémoire, mais en réalité ne le fait pas.

Cependant, je pense que ce que l'auteur essaie de dire est que, puisque que buggyObject crée un paramètre de sécurité qui s'appelle lui-même, même si vous changez de BuggyObject sur l'égalité null (en disant On fait avec l'objet et il peut être nettoyé), l'objet ne sera pas recruté, car il y en a encore une référence dans le Settimeout (). Ceci est techniquement une fuite de mémoire car il n'y a plus aucune référence directe à la fonction de Settimeout afin que vous puissiez l'effacer plus tard (type de délai de zombie si vous voulez).


0 commentaires

7
votes

Ceci est définitivement une fuite de mémoire. Cependant, la consommation de mémoire est si petite et ne peut être mesurée. J'ai fait de petits changements au code source.

  • Je mets tout le code à l'intérieur d'une boucle pour créer le même scénario 100 000 fois
  • J'ai augmenté l'intervalle de minuterie à environ 16 minutes. Cela empêche le navigateur de crash

    Voici le code: xxx

    Fuite de mémoire en chrome

    mon expérience:

    J'ai dirigé le code dans chrome version 34.0.1847.116 m et changements de mémoire capturés à l'aide d'outils de développeur \ Timeline.

    Comme nous pouvons le voir sur la photo, environ 32 Mo de mémoire ont été consommés pour exécuter ce code et après un certain temps, il a été diminué d'environ 30 Mo et resté inchangé inchangé (voir n ° 1). Après plusieurs tentatives de collecte de déchets de Chrome (voir n ° 2) et une collection à ordures forcée manuelle par moi (voir n ° 3, n ° 4), la consommation de mémoire reste inchangée. Il n'y a plus de buggyroject et il n'y a rien que nous puissions faire pour libérer la mémoire. Le seul moyen possible est de fermer le navigateur.

    Qu'est-ce qui cause cela?

    La principale raison de ce comportement est la minuterie. Le rappel de la minuterie et son objet attaché, BuggyObject ne sera pas publié tant que le délai d'attente se produit. Dans notre minuterie de cas se réinitialise et fonctionne pour toujours et que son espace mémoire ne sera jamais collecté même s'il n'y a aucune référence à l'objet d'origine.


3 commentaires

Ce qui est décrit ici ne me semble pas comme une fuite de mémoire. C'est seulement 32 Mo pour 100 000 minuteries en cours d'exécution. La mémoire n'augmente pas!


Si vous continuez à courir le code, il augmentera et ne peut jamais être recueilli.


Dans n'importe quelle application de non-navigateur, il s'agit d'une énorme préoccupation!



1
votes

As Advncd a souligné, la minuterie est exécutée et ajoute encore plus de données sur la pile. Il y a une vue conceptuelle de ce qui se passe: xxx

donc chaque fois qu'une nouvelle variable A est allouée sur la pile qui pousse pour toujours.

Ce que Advncd n'a pas mentionné, cependant, est le fait que vous avez une fonction seinterval () pour faire ce que vous devez faire: avoir la même fonction appelée encore et encore. Maintenant, vous avez toujours une "fuite de la mémoire", mais seuls les paramètres d'initialisation fuient (c'est-à-dire qu'il ne pousse pas chaque fois que la minuterie est de sortir.)

si conceptuel, les appels sont plats et vous évitez la fuite: xxx


0 commentaires