Si je comprends bien, tout ce qui est créé avec un alloc , un nouveau ou une copie doit être publié manuellement. Par exemple:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
Ma question, cependant, est-ce que ce ne serait pas tout aussi valable?:
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
la source
an object
devrait êtrean object that is a subclass of NSObject or NSProxy and doesn't override -autorelease
.NSAutoreleasePool: drain vs release
Puisque la fonction de
drain
etrelease
semble prêter à confusion, il peut être utile de clarifier ici (bien que cela soit couvert dans la documentation ...).À proprement parler, du point de vue général
drain
n'est pas équivalent àrelease
:Dans un environnement compté par référence,
drain
effectue les mêmes opérations querelease
, donc les deux sont en ce sens équivalents. Pour souligner, cela signifie que vous ne fuyez pas une piscine si vous utilisezdrain
plutôt querelease
.Dans un environnement garbage collection,
release
est un no-op. Cela n'a donc aucun effet.drain
, d'autre part, contient un indice pour le collectionneur qu'il devrait "collecter si nécessaire". Ainsi, dans un environnement garbage collection, l'utilisationdrain
aide le système à équilibrer les balayages de collecte.la source
NSAutoreleasePool
. En effet, les pools fonctionnent comme une pile. L'instanciation d'un pool pousse ce pool au sommet de cette pile de pool de libération automatique de threads.-release
fait sortir ce pool de la pile ET de tous les pools qui ont été poussés dessus, mais pour une raison quelconque, n'ont pas été sautés.Comme déjà souligné, votre deuxième extrait de code est correct.
Je voudrais suggérer une manière plus succincte d'utiliser le pool de libération automatique qui fonctionne sur tous les environnements (comptage de ref, GC, ARC) et évite également la confusion drain / libération:
Dans l'exemple ci-dessus, veuillez noter le bloc @autoreleasepool . Ceci est documenté ici .
la source
@autoreleasepool
bloc avec ARC.Non vous vous trompez. La documentation indique clairement que sous non-GC, -drain équivaut à -release, ce qui signifie que le NSAutoreleasePool ne sera pas divulgué.
la source
NSAutoreleasePool
: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…Ce que j'ai lu d'Apple: «À la fin du bloc de groupe de libération automatique, les objets qui ont reçu un message de libération automatique dans le bloc reçoivent un message de libération - un objet reçoit un message de libération pour chaque fois qu'il a reçu un message de libération automatique dans le bloc. "
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
la source
l'envoi de la libération automatique au lieu de la libération à un objet prolonge la durée de vie de cet objet au moins jusqu'à ce que le pool lui-même soit vidé (cela peut être plus long si l'objet est conservé par la suite). Un objet peut être placé plusieurs fois dans le même pool, auquel cas il reçoit un message de libération à chaque fois qu'il a été placé dans le pool.
la source
Oui et non. Vous finiriez par libérer la mémoire de chaîne mais «fuir» l'objet NSAutoreleasePool dans la mémoire en utilisant drain au lieu de release si vous l'exécutiez dans un environnement garbage collection (non géré par la mémoire). Cette "fuite" rend simplement l'instance de NSAutoreleasePool "inaccessible" comme tout autre objet sans pointeurs puissants sous GC, et l'objet sera nettoyé lors de la prochaine exécution de GC, ce qui pourrait très bien être directement après l'appel à
-drain
:Sinon, c'est similaire à la façon dont
-release
se comporte sous non-GC, oui. Comme d'autres l'ont indiqué, il-release
n'y a pas d'opération sous GC, donc le seul moyen de s'assurer que le pool fonctionne correctement sous GC est à travers-drain
, et-drain
sous non-GC fonctionne exactement comme-release
sous non-GC, et communique sans doute ses fonctionnalités plus clairement comme bien.Je dois souligner que votre déclaration "tout ce qui est appelé avec new, alloc ou init" ne doit pas inclure "init" (mais doit inclure "copy"), car "init" n'alloue pas de mémoire, il configure uniquement l'objet (constructeur mode). Si vous avez reçu un objet alloué et que votre fonction n'a appelé init que comme tel, vous ne le libérez pas:
Cela ne consomme pas plus de mémoire que celle avec laquelle vous avez déjà commencé (en supposant que init n'instancie pas les objets, mais vous n'êtes pas responsable de ceux-ci de toute façon).
la source
-[NSAutoreleasePool release]
dans un environnement garbage collection est un no-op.-[NSAutoreleasePool drain]
fonctionne à la fois dans les environnements de référence et de récupération de place.