Erik Rodriguez
Erik Rodriguez

Reputation: 145

iOS NSMutableArray Memory Leak

I'm having a bit of trouble with memory leaks in my objective c code. Could anyone take a look and let me know what they think?

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];
}

The Leaks tool is saying that the leak occurs when fields is allocated, and when I am adding field string to the fields array.

Also, this function is getting called each line of a file that I'm parsing.

Any tips would be helpful.

Thanks!

Upvotes: 0

Views: 1007

Answers (5)

vicsonic
vicsonic

Reputation: 83

You could also take advantage of the properties in objective C to make more clear and efficient your 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];
}

Now, with the modifier retain of the property realArray you can use [NSMutableArray array] that return an autorelease mutable array.

The retain properties manage the retain/release stuff by themselves.

You don't need to use the realArray = nil; line. You've already deallocated the property.

Hope this can help.

Upvotes: 1

Rahul Vyas
Rahul Vyas

Reputation: 28740

Adding to Felz answer above. Use self.realArray when allocating array

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

Because you have created a property for the array so it is better to use "self"

Upvotes: 1

JeremyP
JeremyP

Reputation: 86681

In this piece of code, you break the memory management rules.

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

You do not own the object pointed at by field so you must not release it.

You have overreleased field so the last object to release it (the autorelease pool in your case) is releasing an already dealloc'd object.

Upvotes: 3

Caleb
Caleb

Reputation: 125017

From the docs:

An allocation message does other important things besides allocating memory:

  • It sets the object’s retain count to one (as described in “How Memory Management Works”).

Therefore, you don't need to retain something that you've just alloc'ed.

Upvotes: 2

fsaint
fsaint

Reputation: 8759

This line does a double retain:

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

it is enough

realArray = [[NSMutableArray alloc] init];

Upvotes: 4

Related Questions