2011-10-18 4 views
0

J'ai un peu de mal avec les fuites de mémoire dans mon code c objectif. Quelqu'un pourrait-il jeter un coup d'oeil et me laisser savoir ce qu'ils pensent?iOS NSMutableArray Memory Leak

NSStringArray.h

@interface NSStringArray : NSObject { 

NSMutableArray *realArray; 

} 

@property (nonatomic, assign) NSMutableArray *realArray; 

-(id)init; 
-(void)dealloc; 
@end 

NSStringArray.m

#import "NSStringArray.h" 


@implementation NSStringArray 

@synthesize realArray; 

-(id)init { 

self = [super init]; 
if (self != nil) { 
    realArray = [[[NSMutableArray alloc] init] retain]; 
} 
return self; 
} 

-(void)dealloc { 
[realArray release]; 
realArray = nil; 
[super dealloc]; 
} 

Factory.m

+(NSStringArray *)getFields:(NSString *)line { 
//Divides the lines into input fields using "," as the separator. 
//Returns the separate fields from a given line. Strips out quotes & carriage returns. 

line = [line stringByReplacingOccurrencesOfString:@"\"" withString:@""]; 
line = [line stringByReplacingOccurrencesOfString:@"\r" withString:@""]; 

NSStringArray *fields = [[NSStringArray alloc] init]; 

for (NSString *field in [line componentsSeparatedByString:@","]) { 
    [fields.realArray addObject:field]; 
    [field release];  
} 

return [fields autorelease]; 
} 

L'outil de fuites dit que la fuite se produit lorsque les champs sont alloués, et quand J'ajoute la chaîne de champ au tableau de champs.

De plus, cette fonction est appelée chaque ligne d'un fichier que j'analyse.

Des astuces seraient utiles.

Merci!

Répondre

3

Dans ce code, vous cassez les règles de gestion de la mémoire.

for (NSString *field in [line componentsSeparatedByString:@","]) { 
    [fields.realArray addObject:field]; 
    [field release];  
} 

Vous ne possédez pas l'objet pointé par field si vous ne devez pas le libérer.

Vous avez dépassé le champ de sorte que le dernier objet à libérer (le groupe autorelease dans votre cas) libère un objet déjà désalloué.

+0

C'était le problème! Merci beaucoup! –

4

Cette ligne fait un double retenir:

realArray = [[[NSMutableArray alloc] init] retain]; 

il suffit

realArray = [[NSMutableArray alloc] init]; 
+0

C'est ce que je pensais aussi, mais quand je sors de la retenue, l'application se bloque avec EXEC_BAD_ACCESS. –

+1

@Erik Rodriguez: Alors vous avez un problème ailleurs. – Chuck

+1

Ceci est correct (+1), mais voir ma réponse pour savoir pourquoi vous obtenez le crash lorsque vous laissez la retenue. – JeremyP

1

De the docs:

Un message d'allocation fait d'autres choses importantes en dehors de l'allocation mémoire:

  • Il définit le nombre de rétention de l'objet sur un (comme décrit dans "Comment fonctionne la mémoire ").

Par conséquent, vous n'avez pas besoin de retenir quelque chose que vous venez de alloc'ed.

+0

C'est ce que je pensais aussi, mais quand je sors, l'application se bloque avec EXEC_BAD_ACCESS. Il semble que lorsque le pool autorelease est libéré, c'est lorsqu'il se bloque. –

+0

C'est parce que vous libérez quelque chose que vous ne devriez pas. Veuillez lire la réponse de @ JeremyP, puis lisez les [Règles de gestion de la mémoire] (http://tinyurl.com/6ktdglb). – Caleb

1

Ajout à la réponse Felz ci-dessus. Utilisez self.realArray lorsque l'allocation tableau

self.realArray = [[NSMutableArray alloc] init]; 

Parce que vous avez créé une propriété pour le tableau il est donc préférable d'utiliser « auto »

1

Vous pouvez également tirer parti des propriétés dans l'objectif C make plus clair et efficace votre code:

NSStringArray.h

@interface NSStringArray : NSObject { 
} 
@property (nonatomic, retain) NSMutableArray *realArray; 
@end 

NSStringArray.m

#import "NSStringArray.h" 

@implementation NSStringArray 

@synthesize realArray = _realArray; 

-(id)init { 

self = [super init]; 
if (self) { 
    self.realArray = [NSMutableArray array]; 
} 
return self; 
} 

-(void)dealloc { 
[_realArray release]; 
[super dealloc]; 
} 

Maintenant, avec le modificateur retain de la propriété realarray vous pouvez utiliser [NSMutableArray array] qui renvoient un autorelease tableau mutable.

Les propriétés de retenue gèrent elles-mêmes les éléments de conservation/libération. Il n'est pas nécessaire d'utiliser la ligne realArray = nil;. Vous avez déjà désaffecté la propriété.

Espérons que cela peut aider.

+0

Excellent excellent conseil! Je suis encore tout nouveau à l'objectif-c et les meilleures pratiques sont les bienvenues! Merci! –