2008-12-01 5 views
1

Après avoir obtenu le objectEnumerator dans le code suivant, le nombre de retenue set1 passe à 3. J'ai été surpris de le voir parce que je ne m'attendais pas à ce qu'il change. J'ai cherché le documentation et ne peux pas trouver où cet effet est expliqué. Je suppose que les retenues supplémentaires sont probablement configurées pour être auto-libérées par la logique d'énumération Cocoa et n'auront vraiment aucun effet dans la boucle d'événement actuelle. Il est logique que la logique objectEnumerator ait besoin d'une référence à set1 mais j'aimerais savoir pourquoi ils ont été créés. Voici la raison: si je suppose que set1 a retenu le compte zéro après la publication dans le code, alors je pourrais essayer de réutiliser un autre nouvel ensemble. Cela ne causerait-il pas de problèmes puisque set1 pointe maintenant vers un objet/une adresse complètement différent? Pour les points "bonus", y a-t-il un moyen d'énumérer le pool autorelease, voir ce qu'il contient réellement? TIAPourquoi NSSet objectEnumerator incrémente-t-il le nombre de rétention?

#import <Foundation/NSObject.h> 
#import <Foundation/NSSet.h> 
#import <Foundation/NSValue.h> 
#import <Foundation/NSEnumerator.h> 
#import <Foundation/NSAutoreleasePool.h> 
#import <Foundation/NSString.h> 

#import <stdio.h>; 

// macro to create an integer number: 
#define INTOBJ(v) [NSNumber numberWithInt: v] 

int main (int argc, char *argv[]) 
{ 
    NSAutoreleasePool *pool = [NSAutoreleasePool new]; 

    //Make set 
    NSMutableSet *set1 = [[NSMutableSet alloc] initWithObjects: 
     INTOBJ(1), INTOBJ(2), INTOBJ(5), INTOBJ(10), nil]; 

    printf("set1 #%lu\n", [set1 retainCount]); 

    //Get enumerator of the set. This is where the retain count goes to 3: 
    NSEnumerator *setEnum = [set1 objectEnumerator]; 
    printf("setEnum #%lu\n", [setEnum retainCount]); 
    printf("set1 #%lu\n", [set1 retainCount]); 

    //Iterate through the collection: 
    printf("["); 

    NSNumber *element; 
    while ((element = [setEnum nextObject]) != nil) 
     //do some this with item. printf is just for debugging: 
     printf(" %i ", [element intValue]); 

    printf("]\n"); 
    printf("set1 #%lu\n", [set1 retainCount]); 

    [set1 release]; 
    printf("set1 after release #%lu\n", [set1 retainCount]); 

    //More logic could go here reusing variable set1 since I assumed retain count = 0 

    [pool release]; 

    return 0; 
} 

Répondre

4

Ce n'est généralement pas une bonne idée de s'appuyer sur le nombre de rétention d'objets, car c'est un détail interne de la structure. Au lieu de cela, assurez-vous que votre code adhère aux principes de gestion de la mémoire, en particulier en veillant à ce que les fonctions conserver/nouveau/copier et relâcher/autorelease soient équilibrées.

+0

Je suis l'un des développeurs .NET non lavés à se lancer dans Obj-C, donc je rate le GC managé. Je commence à manipuler les comptes de retenue grâce à des gens comme vous. Dans .NET, les variables sont "libérées" lorsqu'elles sont hors champ et elles ne sont pas référencées. Que pensez-vous de ce post: http://www.kickingbear.com/blog/?p=17 –

+0

Je peux comprendre pourquoi vous avez défini ces macros, mais elles me tromperaient dans une révision de code ;-) –

1

Réutiliser set1 après la sortie ne causera pas de problèmes, car le nombre de retenir est l'objet référencé par la set1 variable non sur la variable elle-même.

2

Vraisemblablement, l'énumérateur conserve la collection de sorte qu'elle ne soit pas désallouée pendant l'énumération. Un énumérateur sans collection valide à énumérer ne fonctionnerait pas très bien. En fait, la seule façon pour l'agent recenseur d'être sûr qu'il fonctionnera est de conserver la collection qu'il énumère. Cela dit, il n'y a vraiment aucune raison de jamais regarder le nombre de retenue d'un objet sauf pour le débogage d'un problème de fuite de mémoire/double libération. Tant que vous suivez les conventions de gestion de la mémoire, vous ne devriez jamais avoir à vous soucier du nombre de retenues d'un objet.

Questions connexes