2010-11-13 3 views
1

Je fais un bazar de créer un objet dans une méthode et de le renvoyer à une variable. Comme dans this post je sais que je devrais libérer un objet dans ce cas, mais quand je le fais, il se bloque.La création d'un objet autoreleased dans une méthode et le retour à une variable instanciée provoquent un plantage

J'ai écrit une méthode pour créer un tableau d'images et retourner ce tableau. Il ressemble à ceci:

- (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames { 
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames]; 
    for (int i = 1; i <= numberFrames; ++i) { 
     NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i]; 
     [imageArray addObject:[UIImage imageNamed:imageName]]; 
     [imageName release]; 
    } 
    return imageArray; 
} 

Je l'appelle comme ceci:

NSMutableArray *imageArray; 
imageArray = [self createImagesFor:@"jumping" withFrames:2]; 
self.animationImages = imageArray; 
[imageArray release]; 

Cependant, quand je lance l'analyseur de construction, il compile, mais avec la plainte suivante:

fuite potentielle d'un objet affecté à la ligne 109
1. La méthode renvoie un objet Objective-C avec un nombre de retenue +1 (référence propriétaire)
2. Objet l'objet affecté à la ligne 109 est renvoyé par une méthode dont le nom ('createImagesFor: withFrames:') ne contient pas 'copy' ou commence par '' new 'ou' alloc '. Cela constitue une violation des règles de la convention de nommage données dans le Guide de gestion de la mémoire pour le cacao (objet fuite)

J'ai regardé le document memory management mais autre que autoreleasing la variable (ce qui tombe en panne), je ne suis pas sûr où je vais mal. Voilà comment j'autoreleased il:

NSMutableArray *imageArray = [[[NSMutableArray alloc] initWithCapacity:numberFrames]autorelease]; 

J'ai essayé en conservant le * imageArray comme suggested here comme ceci:

NSMutableArray *imageArray; 
[imageArray retain]; 
    imageArray = [self createImagesFor:@"jumping" withFrames:2]; 
    self.animationImages = imageArray; 
    [imageArray release]; 

Mais cette plante aussi.

L'analyseur suggère que je change le nom de la méthode à quelque chose comme 'newCreateImagesFor: withFrames:' mais je ne vois pas comment cela corrige les choses?

Merci pour l'aide.

Michael

Répondre

2
- (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames { 
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames]; 
    for (int i = 1; i <= numberFrames; ++i) { 
     NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i]; 
     [imageArray addObject:[UIImage imageNamed:imageName]]; 
     [imageName release]; 
    } 
    return imageArray; 
} 

retourne un objet imageArray qui a un nombre de conserver 1 mais non dédouanées automatique, analyseur statique clang vous mettre en garde à ce sujet, et il est tout à voir avec convention de nommage, parce que votre méthode n'est pas nommé être comme newImagesFor... ou allocImagesFor... ou copyImagesFor....


NSMutableArray *imageArray; 

[imageArray retain]; 
// sending message to nil, does nothing 

imageArray = [self createImagesFor:@"jumping" withFrames:2]; 
// imageArray has a retain count of 1 
// and it is an autoreleased object 

self.animationImages = imageArray; 

[imageArray release]; 
// retain count = 0, will be dealloc'd, 
// however it is already in the autorelease pool, 
// it will be over-released at the end of current event run loop 

Lorsque vous déclarez imageArray, il est un pointeur NULL à la classe NSMutableArray, l'envoi d'un message, dans votre cas retain, un pointeur NULL dans Objective-C est possible et ne jetterai pas une exception .


Si vous utilisez un accesseur de propriété pour mettre en cache votre objet imageArray, votre accesseur de propriété doit être déclarée pour conserver l'objet que vous attribuez à

@property (retain) NSMutableArray *imageArray; 

Maintenant que votre méthode retourne correctement un autoreleased imageArray, et vous avez un accesseur de propriété correcte, tout ce qui est nécessaire est

NSMutableArray *imageArray; 
imageArray = [self createImagesFor:@"jumping" withFrames:2]; 
self.animationImages = imageArray; 
+0

Ok, je vois - je devrais utiliser des propriétés pour contenir les objets auto-libérés, et ne pas trop les relâcher. Et puisque j'utilise des propriétés, je n'ai pas besoin de m'inquiéter qu'elles seront autoreleased trop tôt. Merci! – Smikey

+1

"Lorsque vous déclarez imageArray, il s'agit d'un pointeur nul vers la classe NSMutableArray". Seules les variables d'instance non initialisées sont garanties nulles. Les variables locales non initialisées peuvent être nulles ou peuvent être un nombre aléatoire de la dernière fois que le bloc de mémoire dans lequel elles sont stockées a été utilisé. – grahamparks

+0

@Adam Ko: est-ce parce que la variable imageArray est une variable de pile pour la fonction et une fois l'appel de fonction terminé, le pointeur de la pile est désalloué et un autre accès utilisant le pointeur désalloué a causé son crash. – prajul

5

Vous devriez changer la dernière ligne du premier bloc de code à return [imageArray autorelease] et de se débarrasser de la libération dans la seconde partie (vous ne jamais normalement pas besoin de libérer des objets retournés par les appels de méthode). C'est ce sur quoi portent les plaintes de l'analyseur. Cependant, je ne vois pas pourquoi cela causerait un crash.

Comment est définie la propriété animationImages? Cela pourrait être la source de vos problèmes.

+0

Super - c'est logique. J'étais en train de relâcher l'objet qui devait causer l'accident. Et cela fonctionne bien maintenant, surtout quand je déclare les accesseurs de propriété, plutôt que d'instancier à la volée. Merci! – Smikey

Questions connexes