11
votes

Ce code pourrait-il causer des fuites de mémoire?

Cela causerait-il une fuite de mémoire?

for ( var i=0 ; i< 1000 ; i++)
{
  var mc:MovieClip ; //<<<<<<< INSIDE LOOP
   mc = new MovieClip() ;
   mc.addEventListener( MouseEvent.CLICK , onClick) ;
}


2 commentaires

Ni les deux ne provoquent aucune fuite de mémoire à ce stade, car vous pourriez avoir besoin que les 1000 MovieClips soient cliqués. Ce n'est que lorsque vous avez fait avec MovieClips et souhaitez-vous les supprimer de la mémoire que le problème de l'auditeur d'événement entre en jeu. La réponse de Ascension est correcte mais le mot «serait» important.


Tout le monde ici, je suis corrigé. Je ne ferai jamais de nouveau confiance à la documentation Adobe. Voir ma réponse mise à jour. Ma réponse actuelle est fausse.


3 Réponses :


6
votes

mise à jour, réponse correcte

Ma réponse originale était fausse et je m'excuse sincèrement. Je laisserai tous mes commentaires et informations condescendant intacts afin que la honte puisse me rappeler à jamais de ne jamais faire confiance à Adobe. La documentation actuelle dit maintenant:

"Si vous n'avez plus besoin d'un écouteur d'événement, supprimez-le en appelant ReimendeventListener () ou des problèmes de mémoire pourraient résulter. Les auditeurs d'événements ne sont pas automatiquement supprimés de la mémoire car le collecteur des ordures ne retire pas l'écoute Tant que l'objet d'expédition existe (sauf si le paramètre UseWeakReferFerence n'est défini sur TRUE). "

Notez que les auditeurs d'événements sont des ordures recueillies, il existe une référence faible ou non, tant que l'objet d'expédition est supprimé en premier. Donc, dans ces deux cas, ils ne causeront jamais de fuite de mémoire. Je demande à l'op de désigner ma réponse comme correcte et de donner la réponse au crédit / réponse correcte + upvotes à @MALYNGO.

Original (erroné) Réponse et (MIS) Les informations suit


Les deux le feraient. La liaison d'un écouteur d'événement crée une référence forte à l'objet d'origine et donc le collecteur des ordures ne le nettoie pas. Vous devez supprimer les auditeurs d'événements explicitement ou les spécifier comme des références faibles, qui doivent être l'un des paramètres de AddeventListener.

pour les personnes qui plaident que les auditeurs n'empêcheront pas d'autres objets d'être des ordures recueillies

http://gingbinger.com / 2010/07 / ActionScript-3-0-Events-the-Myth-of-UseWeakReference /

Résumé de l'article:

"Imaginez que notre joueur meurt, et nous voulons qu'il soit nettoyé. Cependant, l'auditeur d'événements crée une référence de la scène au lecteur. La scène est l'objet d'affichage le plus haut et est toujours accessible. Par conséquent, lorsque la Le processus de balayage de marque est exécuté, cet écouteur d'événement permet au collecteur des ordures de sauter de l'étape à l'objet de notre joueur, même si nous avons effacé toutes les autres références et supprimées de la liste d'affichage. "

Il reste donc au moins un scénario où un auditeur d'événement seul, fortement lié, peut empêcher un objet d'être collecté .

solution de meilleure pratique:

1) Retirez-le de la liste d'affichage.
2) Si c'est un MovieClip, dites-le d'arrêter ().
3) Supprimer tous les auditeurs d'événements que l'objet a créé.
4) Effacer toutes les références des objets parents en les fixant à NULL.

à nouveau à nouveau

Une fuite de mémoire ne signifie pas nécessairement que vous verrez la mémoire d'applications en croissance continue. Une fuite de mémoire peut également simplement décrire la mémoire qui est allouée et persiste pour la durée de vie de l'application, quand elle devrait être recyclée. Quelque chose comme ce code de test ne sera pas très facilement détectable. Mais faire cela arriver n fois plus d'une heure de long jeu et je vous garantis que cela va montrer. J'ai eu la même situation dans un algorithme de cryptage que j'ai écrit une fois. Après un certain temps, mon application a commencé à racler à 10 ou moins de cadres par seconde, car le VM avait mangé une tonne de mémoire, il n'utilisait plus encore plus, il l'utilisait toujours.


0 commentaires

1
votes

Les deux exemples sont identiques, que ActionScript est basé sur Ecmascript 3 qui n'a pas de portée de bloc.

EDIT: Laissez-moi être plus précis: il n'y a pas de périmètre de bloc, mais il existe une portée de la fonction dans ActionScript.

Comme avec la fuite de mémoire, les objets resteront en mémoire.


3 commentaires

"N'a pas de portée de bloc" est faux. Si vous voulez dire que la portée n'a aucune incidence sur la répartition de la mémoire et la désaffectation qui est une histoire différente, mais simplement dire qu'il n'y a pas de périmètre de bloc lui-même est faux.


Je dirais réellement que cela est vrai tant que vous ne comptez pas une fonction de blocage et de le traiter comme une portée de son propre. (Qui encore, techniquement vrai).


Je pense que ce qui veut dire que Jnissi, c'est que AS3 utilise une hélage variable afin de déclarer une variable à l'intérieur ou à l'extérieur de la boucle d'avoir le même effet;)



6
votes

Vos 1000 MovieClips auront une référence à la fonction ONCLICK. Pas l'inverse. Donc, si vous posez des questions, c'est si vos 1000 MovieClips deviendront flcs: ils finiront par ne pas avoir d'autre référence.

D'autre part, la référence dans vos mouvements à votre fonction Onclick restera en vie (et le objet il pourrait appartenir à). Si ces MCS ont une autre référence qui les gardera en vie. P>

Le code suivant: p>

import flash.display.MovieClip;
import flash.events.Event;

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP

function enterframe(ev:Event):void
{
    for ( var i=0 ; i< 1000 ; i++)
    {
       mc = new MovieClip() ;
       mc.onClick = function(ev:Event){};
       // Use one of the following lines, comment out the other one
       //mc.addEventListener( MouseEvent.CLICK , onClick) ; // no memory leak
       stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up
    }
}

this.addEventListener(Event.ENTER_FRAME, enterframe);

function onClick(ev:Event):void
{

}


4 commentaires

Le code de test que j'ai fourni ci-dessus crée constamment 1000 mouvements sur chaque image. S'il y avait une fuite de mémoire, la consommation de mémoire a à grandir, car tous ces objets ne seraient pas collectés. mais ils sont. En ajoutant les Movieclips comme auditeurs à la scène, il y a une fuite de mémoire. La référence est toujours du répartiteur à l'auditeur, pas l'inverse. Donc, s'il n'y a plus de référence au répartiteur, il sera détruit, peu importe le nombre d'auditeurs qu'il aurait pu.


Vous êtes 100% à droite monsieur. Je me suis trompé. J'ai mis à jour ma réponse avec plus d'informations. Il semble que Adobe ait ajouté de nouvelles informations depuis la dernière fois que je lis la documentation. J'ai également demandé que ma réponse soit marquée comme incorrecte et que le crédit vous sera donné.


Quel est le point d'ajouter un événement Enter_frame. La boucle n'a-t-elle pas été suffisante?


@Vishwas gagrani La boucle créera 1000 mouvements, puis rien de plus ne se produira. S'il y a une fuite de mémoire, ces 1000 clips ne seront pas recueillies, mais elles ne peuvent pas non plus être globales car il n'est pas nécessaire de ne pas augmenter. En utilisant l'événement Enter_frame et créez de plus en plus de MovieClips sur chaque image, je m'assure d'exploiter la fuite de mémoire. S'il y en a un, la consommation de mémoire augmentera et grandira. S'il n'y en a pas, le GC collectera ces mouvements et les disposera, laissant l'utilisation de la mémoire à un niveau constant.