Le principal problème lié à la mémoire dont vous devez toujours être conscient est la conservation des cycles. Cela se produit lorsqu'un objet a un pointeur fort vers un autre, mais l'objet cible a un pointeur fort vers l'original. Même lorsque toutes les autres références à ces objets sont supprimées, elles se maintiennent les unes aux autres et ne sont pas publiées. Cela peut également se produire indirectement, par une chaîne d'objets qui pourrait avoir le dernier de la chaîne renvoyant à un objet antérieur.
C'est pour cette raison que les qualificatifs __unsafe_unretained
et __weak
propriétaires existent. Le premier ne conservera aucun objet sur lequel il pointe, mais laisse ouverte la possibilité que cet objet s'éloigne et qu'il pointe vers une mauvaise mémoire, tandis que le second ne conserve pas l'objet et se met automatiquement à zéro lorsque sa cible est désallouée. Des deux, __weak
est généralement préféré sur les plates-formes qui le prennent en charge.
Vous utiliseriez ces qualificatifs pour des choses comme les délégués, où vous ne voulez pas que l'objet conserve son délégué et mène potentiellement à un cycle.
Un autre couple de problèmes importants liés à la mémoire est la gestion des objets Core Foundation et de la mémoire allouée à l'aide malloc()
de types comme char*
. ARC ne gère pas ces types, uniquement les objets Objective-C, vous devrez donc toujours les gérer vous-même. Les types de Core Foundation peuvent être particulièrement délicats, car ils doivent parfois être reliés à des objets Objective-C correspondants, et vice versa. Cela signifie que le contrôle doit être transféré dans les deux sens depuis l'ARC lors du pontage entre les types CF et Objective-C. Certains mots clés liés à ce pont ont été ajoutés, et Mike Ash a une excellente description de divers cas de pontage dans sa longue rédaction ARC .
En plus de cela, il existe plusieurs autres cas moins fréquents, mais toujours potentiellement problématiques, que la spécification publiée détaille.
Une grande partie du nouveau comportement, basé sur la conservation des objets tant qu'il y a un pointeur fort vers eux, est très similaire à la récupération de place sur Mac. Cependant, les fondements techniques sont très différents. Plutôt que d'avoir un processus de ramasse-miettes qui s'exécute à intervalles réguliers pour nettoyer les objets qui ne sont plus pointés, ce style de gestion de la mémoire repose sur les règles rigides de conservation / libération que nous devons tous respecter dans Objective-C.
ARC prend simplement les tâches de gestion de mémoire répétitives que nous avons dû faire pendant des années et les décharge sur le compilateur afin que nous n'ayons plus jamais à nous en soucier. De cette façon, vous n'avez pas les problèmes d'arrêt ou les profils de mémoire en dents de scie rencontrés sur les plateformes de récupération de place. J'ai connu ces deux problèmes dans mes applications Mac récupérées et je suis impatient de voir comment ils se comportent sous ARC.
Pour en savoir plus sur la collecte des ordures par rapport à ARC, consultez cette réponse très intéressante de Chris Lattner sur la liste de diffusion Objective-C , où il énumère de nombreux avantages d'ARC par rapport à la collecte des ordures Objective-C 2.0. J'ai rencontré plusieurs des problèmes du GC qu'il décrit.
ARC ne vous aidera pas avec la mémoire non ObjC, par exemple si vous avez
malloc()
quelque chose, vous en avez toujours besoinfree()
.ARC peut être trompé
performSelector:
si le compilateur ne peut pas comprendre ce qu'est le sélecteur (le compilateur générera un avertissement à ce sujet).ARC générera également du code suivant les conventions de dénomination ObjC, donc si vous mélangez le code ARC et MRC, vous pouvez obtenir des résultats surprenants si le code MRC ne fait pas ce que le compilateur pense que les noms promettent.
la source
J'ai rencontré des fuites de mémoire dans mon application en raison des 4 problèmes suivants:
Heureusement, je suis tombé sur le billet de blog suivant et j'ai pu les corriger: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-l probable - culprits/
la source
ARC ne gère pas non plus les types CoreFoundation. Vous pouvez les `` relier '' (à l'aide
CFBridgingRelease()
) mais uniquement si vous allez l'utiliser comme un objet Objective-C / Cocoa. Notez que CFBridgingRelease diminue simplement le nombre de retenues CoreFoundation de 1 et le déplace vers l'ARC d'Objective-C.la source
Xcode 9 fournit un excellent outil pour trouver ce genre de problèmes. Il s'appelle: " Debug Memory Graph ". En l'utilisant, vous pouvez trouver votre objet divulgué par type de classe et vous pouvez voir clairement qui détient une référence forte en le libérant à partir de là résout votre problème. Il détecte également les cycles de mémoire.
Voir plus d'informations sur son utilisation
la source