2011-01-10 2 views
5

Je développe une application iPhone qui utilise principalement le carnet d'adresses et la base de données. Après avoir récupéré environ 3000 contacts du carnet d'adresses, j'attache des étiquettes de chaîne aux contacts (5 pour chaque). Je sauvegarde mes tags dans la base de données.Fuites de mémoire causées par CoreFoundation Framework

Pour les tests de charge, j'ai ajouté 10 000 étiquettes à l'application. Mais lors du test de charge de mon application, j'ai observé des fuites de mémoire qui n'étaient pas liées au code de l'application mais représentaient un ensemble d'instructions. Aussi Instruments a montré Fondation comme la bibliothèque responsable de la fuite (utilisation étendue de NSString, NSDictionary, NSArray qui appartient au cadre de la Fondation). Mon application se bloque après 10 à 15 minutes d'utilisation. Le rapport de crash mentionne que l'application a planté en raison d'une mémoire insuffisante.

Le profilage de la mémoire à l'aide de CLANG n'affiche aucune fuite. Comment puis-je résoudre ces fuites de mémoire? Ces fuites sont-elles le véritable responsable de l'accident? Y a-t-il d'autres outils disponibles pour vérifier les fuites de mémoire?

+1

Cela peut être un problème d'auto-libération. Cela arrive-t-il encore si vous le faites par lots? Autrement dit, dans différentes itérations du runloop? Peut-être emballer l'opération avec sa propre piscine. – Eiko

+0

Oui, j'ai essayé de vider le pool de publication automatique une fois que l'application reçoit un avertissement de la mémoire, mais la vidange de la piscine ne fait également aucun bien. – Aditya

+0

Vous devriez savoir si les fuites sont le coupable, combien de mémoire les instruments disent-ils que vous fuyez? – hooleyhoop

Répondre

4

Je trouve souvent mes fuites disent qu'elles sont causées par Core Foundation (ou tout autre framework d'ailleurs) mais sont vraiment les miennes. À l'exception du simulateur, vous trouverez rarement des fuites excessives dans les cadres.

Si vous ouvrez le panneau d'informations à droite dans Instruments, vous pouvez trouver la liste des méthodes de votre application. Cela vous donnera une indication de l'origine de votre code. Une fuite peut provoquer de nombreuses autres fuites, et vous devrez peut-être trouver le coupable de niveau supérieur pour se débarrasser des plus faibles.

Vous ne devriez pas vous attendre à ce que Clang fasse quoi que ce soit mais trouve les fuites les plus évidentes. C'est très pratique, mais c'est tout, un ajout utile à la compilation.

-1

Essayez de faire des problèmes dans le code u: 1. S'il vous plaît éviter déclaration cacher comme

NSString *string = [dictionary valueForKey:[dictionary2 valueForKey:@"something"]] 

code est:

NSString *key = [dictionary2 valueForKey:@"something"]; 
NSString *string = [dictionary valueForKey:key]; 
key = nil; 
  1. Essayez d'éviter la déclaration avec autorelease et local déclaration comme:

    NSArray * array = [tableau de tableaux NS];

Si u faites cela, assurez-vous que u ont:

NSArray *array = [NSArray array]; 
.... some code where array is using; 
array = nil; 

Une meilleure idée est alloc et libérer immédiatement quand u ne ont pas besoin objet et le mettre à zéro. 3. Vérifiez si vous utilisez des correcteurs. Probablement meilleure idée est d'éviter de l'utiliser, à mon expérience, libérer des fuites de début de classe pour les getters et setters, qui utilisait avant.

Si vous affichez une partie du code u, où vous avez vu la plupart des fuites (les instruments vous donnent la possibilité de cliquer sur les objets qui fuient et voyez le volume des fuites dans le code de programmation).

1

clang n'est pas un vérificateur de fuite. Il ne détecte qu'un petit sous-ensemble de problèmes. Pour le débogage de fuite de mémoire, vous devez vous concentrer sur les instruments, en particulier sur les instruments d'allocation d'objets et de fuites. Assurez-vous de bien comprendre la différence entre les fuites et d'autres sources d'utilisation de la mémoire élevée. Une fois que vous avez déterminé que des objets fuient, utilisez Instruments pour examiner leur trace de pile d'allocation (afin que vous sachiez de quel objet il s'agit) et leur historique de conservation/libération.

Si ce n'est pas une fuite, alors je suggère d'étudier les instructions ici: http: //www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak- using-heapshot-analysis-to-find-indésirable-memory-growth/

+0

Ya j'ai résolu toutes les fuites qui ont été causées par le cadre ce que je pensais était dû au cadre, mais ne l'était pas .. Donc maintenant le problème est avec les affectations ... il y a beaucoup d'allocations faites pendant le cycle de vie de l'application qui causent l'application de planter après 10 minutes d'utilisation. – Aditya

+1

Heapshots sont votre ami. – v01d

1

Vous avez probablement du code qui crée les objets de base. Les fuites vous montrent l'endroit de l'allocation, mais cela est généralement dû à un appel que votre code a fait pour créer l'objet. Vous pouvez regarder la chaîne d'appel dans Instruments et revenir le long de la chaîne d'appel jusqu'à ce que vous arriviez à votre code - c'est l'endroit où vous êtes à l'origine de l'allocation. Maintenant, pour cette allocation, regardez votre gestion de la mémoire pour cet objet: le relâchez-vous quelque temps plus tard?

Il existe de nombreuses façons de ne pas libérer la propriété de mémoire, il est donc difficile de deviner lequel vous pourriez toucher. Ceux que je vois quand j'aide les gens incluent l'allocation d'un objet et son assignation à une variable d'instance via une propriété avec l'attribut retain, quelque chose comme ceci:

@property NSString * myString;

...

self.myString = [[NSString alloc] initWithString: @ "foo"]; Alloc_init crée un objet retenu, self.myString = incrémente à nouveau le nombre de retenues. Si elle est correctement codée, la méthode dealloc libère la propriété via l'un des éléments suivants:

[myString release]; ou self.myString = nil;

Et cela prend soin de la retenue ajoutée avec le self.myString = mais ne prend pas soin de retenir de la création. Solutions, UN des éléments suivants:

myString = [[NSString alloc] initWithString: @ "foo"]; // n'appelle pas la méthode setter donc aucune affectation ne retient - mais n'appelle pas le setter qui pourrait être mauvais s'il n'est pas trivial.

self.myString = [[[NSString alloc] initWithString: @ "foo"] autorelease]; Autorelease libère alloc + init retain.

Maintenant, bien sûr, c'est un exemple artificiel parce que vous utiliseriez probablement vraiment:

self.myString = [NSString stringWithString: @ "foo"];

qui est une méthode de classe retournant une chaîne autoeleased et évite le problème. Mais l'idée est de montrer un exemple simple pour expliquer ce type de problème.

Il existe de nombreuses autres façons de ne pas libérer la mémoire correctement, mais le conseil pour remonter la chaîne d'appel jusqu'à ce que vous arriviez à votre code est la façon d'aller voir où vous déclenchez l'allocation de la mémoire et alors vous pouvez comprendre pourquoi vous ne libérez pas cela correctement.