2010-07-29 4 views
1

Je suis en train d'écrire une application (essentiellement son autre clone iBooks) qui consomme beaucoup de mémoire. Selon les données d'entrée, son empreinte mémoire peut aller jusqu'à 70-80 Mo (en tant qu'états MemoryMonitor) ou même plus.
Cela fonctionne bien pendant un certain temps, mais il a tendance à augmenter son empreinte mémoire au fil du temps.
Ainsi, disons que vous ouvrez un livre et que la mémoire de l'application va de 6 Mo à 60 Mo. Alors, ce qui est censé arriver, c'est que vous fermez le livre et que l'empreinte de la mémoire redescende à 6MB. Et ce n'est pas le cas. Il descend à ~ 30 Mo (selon MemoryMonitor), ce qui entraîne un plantage en quelques itérations.Je ne trouve pas la source d'une fuite de mémoire

Maintenant, la partie intéressante. J'ai essayé clang analyseur statique, mais il ne montre aucun problème (en dehors de pointage sur singletons, etc).
J'ai essayé d'utiliser des instruments de fuite, mais ils montrent que j'ai seulement 2-3KB au total (et il devrait être ~ 24MB +). De plus, je ne suis pas préoccupé par le fait que les instruments me disent la vérité. J'ai vérifié toutes les fuites rapportées par les instruments et je suis certain à 99% qu'il n'y a pas de fuites.
J'ai essayé d'utiliser l'instrument d'allocations, mais cela montre qu'après la fermeture du livre, l'empreinte de la mémoire descend à 6 Mo, ce qui est le nombre désiré. Mais cela n'a pas beaucoup de sens puisque si c'était le cas, l'application ne se serait jamais écrasée. J'ai également essayé d'utiliser le profileur openglES pour le graphique Resource Bytes, mais il montre également aucune fuite ou autre chose suspecte.
Le seul instrument auquel j'avais l'habitude de faire confiance était le moniteur de mémoire, car mon application se bloquait toujours quand elle affichait ~ 110 Mo de mémoire réelle utilisée. Cependant, a) il ne montre pas ce qui alloue la mémoire et b) quand j'ai essayé de l'exécuter plusieurs fois avec la même application, j'ai découvert que ses lectures différaient considérablement d'une exécution à l'autre (différence de 15-20 Mo tout en faisant exactement même).

Alors tous les instruments me disent que mon code est bon (à part le Memory Monitor, qui semble correct mais inutile pour toute mesure) mais qui continue à s'écraser.
Je n'ai aucune idée de ce que je devrais faire ensuite. Je ne peux certainement plus réduire l'empreinte mémoire globale, et je ne peux pas trouver de fuites de mémoire (ce qui est encore le chemin à parcourir je suppose).

Voici donc mes questions:
1) Existe-t-il un moyen de trouver des fuites autres que celles mentionnées ci-dessus? Un autre programme de profilage pour iphone peut-être?
2) J'ai lu des problèmes de défragmentation, comme lorsque vous allouez/réallouez plusieurs objets, puis l'application ne renvoie pas les blocs libérés à OS, ce qui peut rendre impossible l'allocation de gros blocs de mémoire il est trop fragmenté et OS ne vous donne plus de mémoire. Je n'ai jamais vu un bon sujet à ce sujet. Si quelqu'un pouvait épargner un lien vers un sujet connexe, ce serait génial.
3) J'ai essayé de désactiver plusieurs parties du programme, et jusqu'à présent, il semble que tout le problème provient de l'utilisation de CoreText Framework. Je voudrais entendre de toute personne qui a déjà utilisé ce cadre fortement et peut confirmer/nier que des problèmes existent là.
4) - toute autre suggestion--

P.S. Je n'ai inclus aucun extrait de code car le code lui-même est assez volumineux et je ne peux pas réduire la quantité de code suspect à un niveau raisonnable.

Répondre

2

Un peu stupide peut-être, mais quand quelque chose de similaire m'a arrivé, j'ai réalisé que NSZombies était activé . Depuis lors, mon didFinishLaunching: a les lignes suivantes en haut:

if (getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) { 
    NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!"); 
} else { 
    NSLog(@"No NSZombieEnabled or NSAutoreleaseFreedObjectCheckEnabled"); 
} 
+0

Zombies explosés! C'était ça! Incroyable combien de temps j'ai passé à essayer de trouver la source de ce problème. Je suis également surpris que les instruments d'allocation de mémoire/fuites ignorent les zombies dans leur ensemble. – Alexey

+0

Ils ne le font pas, ils le désactivent, c'est pourquoi ils rapportent si peu. C'était une sorte de plus grand indice pour moi dans votre texte. – Kalle

+0

Je ne suis pas certain que les instruments les éteignent. Après que je les ai désactivés manuellement, Memory Monitor a commencé à rapporter des nombres complètement différents, alors que les lectures des instruments de fuites/allocations étaient toujours les mêmes (je cours des instruments avec des allocations + leaks + opengles + moniteur de mémoire). C'est pourquoi je pense qu'ils les ignorent plutôt que de les éteindre. – Alexey

0

Le problème est que les fuites détectent uniquement la mémoire qui est toujours conservée et à laquelle vous n'avez pas de référence.

Dans votre cas, vous avez toujours de la mémoire dont vous avez également des références. En ce qui concerne les fuites, il ne peut pas dire si vous vouliez conserver cette mémoire ou non, donc il ne dit rien.Dans votre situation, la meilleure chose à faire est d'utiliser l'instrument Object Alloc - enregistrer une session, puis pour une région de mémoire croissante - sélectionner la région, et sélectionner l'option "conservé et toujours vivant" sur le côté. Maintenant, passez en revue les objets rapportés et déterminez ce qui est encore retenu, ce qui ne devrait pas être le cas - un bon point de départ est de chercher l'une de vos propres classes encore conservées et de déterminer ce que vous pensiez être désaffecté. Le nouveau XCode dispose également d'un outil qui combine les fuites et l'allocation d'objets, je ne peux rien dire de plus puisqu'il est sous NDA - mais vous voudrez peut-être essayer cela. Je ne sais pas si vous devez l'installer sur un système séparé pour avoir accès aux outils améliorés si ...