9

J'ai rencontré un étrange comportement objc_setAssociatedObject sous ARC. Considérez le code suivant:Objets associés Objective-C qui fuient sous ARC

static char ASSOC_KEY; 

@interface DeallocTester : NSObject 
@end 

@implementation DeallocTester 
- (void) dealloc 
{ 
    NSLog(@"DeallocTester deallocated"); 
    //objc_setAssociatedObject(self, &ASSOC_KEY, nil, OBJC_ASSOCIATION_RETAIN); 
} 
@end 

@implementation AppDelegate 
- (void) applicationDidFinishLaunching:(UIApplication *)application 
{ 
    NSObject *test = [[DeallocTester alloc] init]; 
    objc_setAssociatedObject(test, &ASSOC_KEY, [[DeallocTester alloc] init], 
          OBJC_ASSOCIATION_RETAIN); 
} 

Je crée une instance de DeallocTester, je mets une autre DeallocTester comme un objet associé pour lui, alors tous les deux sont hors de portée.

Je m'attends à ce que le -dealloc du premier objet soit appelé, puis l'objet associé à être libéré aussi, mais je vois le message "DeallocTester deallocated" imprimé une seule fois. Si je décommente la ligne objc_setAssociatedObject dans -dealloc, le deuxième objet est également désalloué.

La référence Objective-C indique que les objets associés sont désalloués automatiquement lors de la destruction de l'objet. Est-ce un compilateur/ARC/quel que soit le problème ou ai-je oublié quelque chose?

Mise à jour

Ce code exemple fonctionne en fait, si vous l'exécutez à partir d'un projet flambant neuf. Mais j'ai deux projets ARC-enabled où ce n'est pas le cas. Je vais faire une enquête et fournir un meilleur échantillon.

Update 2

J'ai rempli un rdar://10636309, Associated objects leaking if NSZombie objects enabled in ARC-enabled project

+0

Si vous utilisez LLVM3 + pourquoi vous utilisez des objets associés ? Vous pouvez simplement créer des iVars et des propriétés dans les catégories de la classe à la place. – Abizern

+0

@Abizern Je vais ajouter des ivars à 'NSObject', les ivars AFAIR peuvent être ajoutés à une catégorie d'extension de classe seulement, pas arbitraire. – iHunter

+0

@Abizern Vraiment? Comment créez-vous un ivar dans une catégorie? – jlehr

Répondre

9

J'ai trouvé une source de problème - j'avais NSZombie objets activés dans mes deux projets où ce bogue apparaît. Pour autant que je sache, lorsque les objets zombies sont activés, les instances normales sont remplacées par NSZombie lors de la désallocation, mais tous les objets associés sont laissés en vie! Méfiez-vous de ce comportement!

J'ai créé un rdar://10636309

Mise à jour: Il y a un workaround par Cédric Luthi, et cette question semble être fixé dans iOS 6.

+0

Heh, une autre bonne raison de ne pas laisser 'NSZombie' activé par défaut. – jlehr

+0

@jlehr Et quelles sont les autres raisons? Je les ai toujours permis dans mes projets, et n'ai pas vu d'inconvénients jusqu'ici. Est-ce que je manque quelque chose? Je vous remercie. – iHunter

+1

Quitter les zombies activés peut masquer une variété de problèmes et, bien sûr, votre application perd beaucoup de mémoire. – jlehr

1

Le code affiché fonctionne exactement comme annoncé dans l'ARC. J'ai réécrit votre implémentation dealloc pour aider à rendre les choses un peu plus évidentes.

- (void)dealloc 
{ 
    NSLog(@"deallocating %@", self); 
} 

Voici le journal résultant:

2012-01-03 06:49:39.754 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x6878800> 
2012-01-03 06:49:39.756 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x688b630> 

Êtes-vous sûr que vous compilez avec l'ARC activé?

+0

Wow! Quelle version OS/XCode utilisez-vous? – iHunter

+0

J'ai couru ceci dans Xcode 4.2 sur 10.7.2. – jlehr

+0

Moi aussi. Je vais maintenant vérifier à nouveau dans le projet frais. – iHunter

Questions connexes