201 votes

Objective-C: Pourquoi autorelease (@autoreleasepool) est-il toujours nécessaire avec ARC?

Pour la plupart, avec ARC (Automatic Reference Counting), nous n'avons pas besoin de penser à propos de la gestion de la mémoire avec l'Objective-C objets. Il n'est pas permis de créer NSAutoreleasePools plus, cependant il y a une nouvelle syntaxe:

@autoreleasepool {
    …
}

Ma question est, pourquoi aurais-je besoin de ce lorsque je ne suis pas censé être manuellement libération/autoreleasing ?


EDIT: Pour résumer ce que je suis sorti de toutes nous répondons et commentaires succinctement:

Nouvelle Syntaxe

@autoreleasepool { … } est une nouvelle syntaxe pour les

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
…
[pool drain];

Plus important encore,

  • L'ARC utilise autorelease ainsi que la libération
  • Il a besoin d'un autorelease pool en place pour le faire
  • L'ARC n'a pas créer l'autorelease pool pour vous cependant,
  • Le thread principal de chaque Cacao application dispose déjà d'un autorelease pool en elle
  • Il y a deux occasions où vous voudrez peut-être faire usage d' @autoreleasepool
    • Lorsque vous êtes dans un thread secondaire et il n'y a pas d'auto-libération de la piscine, vous devez faire votre propre pour éviter les fuites, comme myRunLoop(…) { @autoreleasepool { … } return success; }
    • Lorsque vous souhaitez créer une piscine locale, comme mattjgalloway a indiqué dans sa réponse

226voto

mattjgalloway Points 24217

L'ARC n'a pas à se débarrasser de conserve, les rejets et les autoreleases, il ajoute juste le nécessaire pour vous. Donc il y a encore des appels à retenir, il y a encore des appels à la libération, il y a encore des appels à autorelease et il y a encore des auto release piscines.

L'un des autres modifications apportées à la nouvelle Clang 3.0 compilateur et de l'ARC, c'est qu'ils remplacé NSAutoReleasePool avec l' @autoreleasepool directive de compilation. NSAutoReleasePool a toujours un peu d'un "objet" de toute façon, et ils l'ont fait en sorte que la syntaxe de l'aide de l'un n'est pas le confondre avec un objet de sorte qu'il est généralement un peu plus simple.

Donc, fondamentalement, vous avez besoin d' @autoreleasepool parce qu'il y a encore de l'auto release piscines à s'inquiéter. Vous n'avez pas besoin de s'inquiéter à propos de l'ajout en autorelease des appels.

Un exemple d'utilisation d'un auto release de la piscine:

- (void)useALoadOfNumbers {
    for (int j = 0; j < 10000; ++j) {
        @autoreleasepool {
            for (int i = 0; i < 10000; ++i) {
                NSNumber *number = [NSNumber numberWithInt:(i+j)];
                NSLog(@"number = %p", number);
            }
        }
    }
}

Un très artificiel exemple, c'est sûr, mais si vous n'avez pas l' @autoreleasepool à l'intérieur de l'extérieur for-boucle, alors vous seriez en libérant 100000000 objets plus tard, plutôt que de 10000 chaque fois que l'extérieur de la for-boucle.

Mise à jour: Voir aussi cette réponse - http://stackoverflow.com/a/7950636/1068248 - pourquoi @autoreleasepool y a rien à faire avec l'ARC.

Mise à jour: J'ai pris un coup d'oeil dans les entrailles de ce qui se passe ici et écrit sur mon blog. Si vous prenez un coup d'oeil vous verrez exactement ce que l'ARC est en train de faire et comment le nouveau style @autoreleasepool et comment il introduit un endoscope est utilisé par le compilateur pour en déduire des informations sur ce qui conserve, les rejets et autoreleases sont nécessaires.

18voto

outis Points 39377

@autoreleasepool n'a pas d'autorelease quoi que ce soit. Il crée un autorelease pool, de sorte que lorsque la fin du bloc est atteint, les objets qui ont été autoreleased par l'ARC, tandis que le bloc a été active sera envoyé libération des messages. Apple Avancé de Gestion de la Mémoire Guide de Programmation l'explique ainsi:

À la fin de l'autorelease pool de bloc, les objets qui ont reçu une autorelease message dans le bloc de l'envoi d'un message de libération-un objet reçoit un message de libération pour à chaque fois qu'il a été envoyé un autorelease message dans le bloc.

9voto

nacho4d Points 12879

Les gens comprennent souvent mal à l'ARC pour un certain type de la collecte des ordures ou autres. La vérité est que, après un certain temps les gens de chez Apple (merci à llvm et clang projets) s'est rendu compte que l'Objective-C est la mémoire de l'administration (tous les retains et releases, etc.) peut être entièrement automatisée, au moment de la compilation. C'est, juste en lisant le code, même avant de l'exécuter! :)

Pour ce faire il existe une seule condition: Nous DEVONS suivre les règles, sinon le compilateur ne sera pas en mesure d'automatiser le processus au moment de la compilation. Donc, afin de nous assurer de ne jamais enfreindre les règles, nous ne sommes pas autorisés à écrire explicitement release, retain, etc. Ces appels sont Automatiquement injecté dans notre code par le compilateur. Donc en interne, nous avons encore autoreleases, retain, release, etc. Il est juste que nous n'avez pas besoin d'écrire plus.

L'Un d'ARC est automatique au moment de la compilation, ce qui est beaucoup mieux qu'au moment de l'exécution, comme la collecte des ordures.

Nous avons encore @autoreleasepool{...} parce que l'avoir n'est pas tout casser les règles, nous sommes libres de créer, vidange de la piscine à tout moment nous en avons besoin :).

3voto

DougW Points 9027

C'est parce que vous avez toujours besoin de fournir au compilateur des indications sur le moment où il est sûr que les objets lancés automatiquement soient hors de portée.

-4voto

Glenn Maynard Points 24451

Il semble y avoir beaucoup de confusion sur ce sujet (et au moins 80 personnes qui sont sans doute maintenant confus au sujet de ce et pensent qu'ils ont besoin de l'arroser @autoreleasepool autour de leur code).

Si un projet (y compris ses dépendances) utilise exclusivement de l'ARC, puis @autoreleasepool ne doit jamais être utilisé et ne rien faire d'utile. ARC poignée de libérer les objets au bon moment. Par exemple:

@interface Testing: NSObject
+ (void) test;
@end

@implementation Testing
- (void) dealloc { NSLog(@"dealloc"); }

+ (void) test
{
    while(true) NSLog(@"p = %p", [Testing new]);
}
@end

affiche:

p = 0x17696f80
dealloc
p = 0x17570a90
dealloc

Chaque objet du Test est libéré dès que la valeur est hors de portée, sans attendre d'autorelease pool de sortie de la. (La même chose se produit avec le NSNumber exemple; cette juste nous permet d'observer le dealloc.) L'ARC ne pas utiliser autorelease.

La raison @autoreleasepool est encore autorisée est mixte de l'ARC et de la non-ARC projets, qui n'ont pas encore complètement passée à l'ARC.

Si vous appelez en dehors de l'ARC de code, il peut retourner un autoreleased objet. Dans ce cas, la au-dessus de la boucle de fuite, depuis l'autorelease pool ne sera jamais quitté. C'est l'endroit où vous souhaitez mettre un @autoreleasepool autour du bloc de code.

Mais si vous avez complètement l'ARC de transition, puis oublier autoreleasepool.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X