Aller au contenu

Etrange probleme de fuite mémoire


Alocaly

Recommended Posts

Bonjour à tous,

Il m'est arrivé un truc étrange sur mon appli, et je n'arrive pas trop à comprendre...

Dans mon appli, j'ai une activity pour le menu, et une autre pour la page de jeu.

Dans la création de l'activity de jeu, j'alloue un objet 'dictionnaire', qui alloue un gros buffer de 1.5 Mo ( environ ) et charge dedans mon dictionnaire ( c'est un jeu de lettres ).

Et jusqu'à présent, je ne m'en occupais pas plus que ca.

Puis en mettant en place un systeme de rapport de crash, je me suis apercu que pas mal de gens crashaient car ils dépassaient la taille mémoire autorisée pour une appli ( 16 Mo ).

En analysant plus ce qui se passait, je me suis apercu que lorsqu'on retourne au menu, puis qu'on repart vers la page de jeu, la libération mémoire est plus qu'aléatoire.

Et dans certaines conditions que je n'ai pas bien saisi, les allocs se succèdent sans déallocation, et on obtient finalement ce crash...

J'ai finalement assez facilement corrigé ce bug :

* d'abord en mettant mon dictionnaire comme un singleton de l'appli,

* puis, bien plus simplement - pour essayer de comprendre ce qui se passait - en mettant le dictionnaire à null lorsque je quitte l'activity du jeu.

Mais ca me fait me poser des questions :

Pourquoi je ne peux pas me reposer entièrement sur le garbage collector de Java ??????

* Les activity ne sont pas détruites après le onDestroy ?

* le garbage collector attend trop longtemps pour se lancer, et, hop, c'est trop tard ! ( en meme temps, je l'appelais dans la page de menu, et ca n'améliorait pas _du_tout _ les choses...)

Je ne suis pas un pro des garbages collectors, mon truc à moi, c'est plutot le C++ où je dois écrire mon propre allocateur pour tout controller, donc je ne sais pas trop quoi conclure...( le C++, ca crash sans doute plus, mais je sais pourquoi... enfin normalement...)

Quelqu'un aurait une bonne idée ?

Merci pour toute suggestion,

Alocaly / Emmanuel

Lien vers le commentaire
Partager sur d’autres sites

Yep, j'ai essayé ( bon , avec System.gc(), mais j'ai bien l'impression que c'est la même chose ), mais ça ne changeait rien...

D'ailleurs la doc indique pour ces deux fonctions que c'est pour proposer à l'OS de lancer la garbage collection, mais qu'il n'y a pas de garantie qu'elle soit faite !

Cela dit, mon probleme mis à part, je pense que c'est une bonne idée de le faire à des moments clé comme tu le fais !

Lien vers le commentaire
Partager sur d’autres sites

Le garbage collector s'occupe seul de la libération de la mémoire. Ce n'est pas au développeur de dire quand ce dernier doit passer : en clair il n'a aucun contrôle dessus. Le garbage collector passe quand bon lui semble et bloque tout sur son passage .... attention à vos interfaces graphiques ;)

Si le garbage collector ne semble pas passer c'est simplement qu'il n'y a pas d'objet désallouable c'est à dire sur lequel aucun autre objet ne pointe (objet lui même non pointé, etc, etc.). Dans ton cas il y a donc n'y a qu'une seule possibilité. Le GC considère qu'il n'y a rien à désallouer (et donc que tu dépasse la taille allouable à force de créer des objets et de conserver des références dessus).

Le GC d'Android est loin, trés loin, d'être parfait mais il fonctionne parfaitement. Si il y a une entité à blamer ce n'est certainement pas le GC :)

Lien vers le commentaire
Partager sur d’autres sites

Le garbage collector s'occupe seul de la libération de la mémoire. Ce n'est pas au développeur de dire quand ce dernier doit passer : en clair il n'a aucun contrôle dessus. Le garbage collector passe quand bon lui semble et bloque tout sur son passage .... attention à vos interfaces graphiques ;)

Si le garbage collector ne semble pas passer c'est simplement qu'il n'y a pas d'objet désallouable c'est à dire sur lequel aucun autre objet ne pointe (objet lui même non pointé, etc, etc.). Dans ton cas il y a donc n'y a qu'une seule possibilité. Le GC considère qu'il n'y a rien à désallouer (et donc que tu dépasse la taille allouable à force de créer des objets et de conserver des références dessus).

Le GC d'Android est loin, trés loin, d'être parfait mais il fonctionne parfaitement. Si il y a une entité à blamer ce n'est certainement pas le GC :)

Hum... Ok, je comprends bien ca : tant qu'on a des références qui trainent sur notre objet, il ne sera pas détruit.

Mais ce qui est troublant, là, c'est que le simple fait de mettre à NULL la référence que j'ai dans mon activity 'Game' sur son ondestroy suffit à résoudre le probleme : ca signifie donc bien que la seule référence qui traine sur ce dictionnaire est mon activité game.

De la meme facon, quand je n'avais pas fait d'action pour résoudre ce probleme, la plupart du temps, la mémoire augmentait 'un peu trop', mais exploser la mémoire s'averait plutot compliqué. Donc la déallocation avait bien lieu. Juste pas assez souvent, ou trop tard...

Moi je m'attendais donc à ce que, apres onDestroy, l'OS essaye tout seul de détruire l'activity 'Game', et donc mette tout seul ( et assez vite de préférence) cette référence à null, et détruise mon dictionnaire.

D'où mon interrogation et ma question. Je ne pensais pas trop à blamer le GC, je suis sur qu'il fait ce qu'il faut, mais je me demandais surtout si il y avait des limites dont je n'avais pas pris conscience.

Par exemple, est-ce qu'il serait possible que des activities à moitié détruites trainent en mémoire pendant plus longtemps que je n'aurais pu le croire ( par exemple à cause des toasts, ou que sais-je encore... )

En gros, il dit que t'as mal codé :)

:)

Ca, mon bon monsieur, c'est bien possible...

Lien vers le commentaire
Partager sur d’autres sites

En gros, il dit que t'as mal codé :)

J'ai pas dit ça :) Même si mon explication pouvait peut-être le faire penser ^^

@Alocaly : C'est vrai que le fait de mettre ta référence à null et que le GC libère alors la mémoire est bizarre. Comme ça je n'ai pas de solution mais je persiste sur le fait que le GC marche parfaitement :) Autre petit point, rappelez vous que vous êtes sur des terminaux mobiles et donc contraints :s. La "heap" n'est "que" de 16Mo et donc allouer des dictionnaires de 1,5Mo commence à impacter sérieusement sur l'application (quand on commence à y ajouter le graphique, les Activity, etc.)

Lien vers le commentaire
Partager sur d’autres sites

c'est clair....le dictionnaire devrait être en base de données.... non ?

Définitivement : NON !!!!!

C'est ce que je faisais auparavant, et l'appli était beauuuuuuuuuuucoup trop grosse !!

Pour le détail de mes aventures :

http://androidblogger.blogspot.com/2009/05/how-to-ship-application-with-pre-baked.html

Sinon, j'ai pas grand chose à coté, donc depuis que mis ma référence à null, je suis bien loin des 16 Mo ( aux alentours de 4, ce qui me semble raisonnable )

Emmanuel / Alocaly

Lien vers le commentaire
Partager sur d’autres sites

Rejoignez la conversation

Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.

Invité
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...