Leak in NSMutableArray category that returns array filled with NSNull
I currently have a NSMutableArray category that creates a NSMutableArray propagated with NSNulls. When I run this code in Instruments it tells me I have a leak here (read comment to see where)
#import "NSMutableArray+NSNull.h"
@implementation NSMutableArray (NSNull)
-(id)initWithNullCapacity:(int)capacity{
self = [super init];
if (self) {
//Leak on [self init]
NSMutableArray *array = [self init];
for (unsigned i = 0; i < capacity; i++)
{
[array addObject:[NSNull null]];
}
self = array;
}
return self;
}
EDIT:
This is where I invoke the method:
#import "TWVStatData.h"
#import "NSMutableArray+NSNull.h"
@implementation TWVStatData
@synthesize creationTime;
@synthesize graphs;
@synthesize elements;
@synthesize type;
-(id)init{
if(self == [super init]){
type = -1;
creationTime = [[NSDa开发者_高级运维te alloc] init];
graphs = [[NSMutableArray alloc] initWithNullCapacity:3];
elements =[[NSMutableArray alloc] init];
}
return self;
}
This is going to be tricky, primarily because of how NSArray
works underneath. I would recommend doing this:
- (id)initWithNullCapacity:(NSUInteger)capacity {
NSMutableArray *nulls = [NSMutableArray array];
for (NSUInteger i = 0; i < capacity; i++) {
[nulls addObject:[NSNull null]];
}
return [self initWithArray:nulls];
}
I think the problem is stemming from the assignment to self
, though I'm not sure of that. NSArray
does some funky optimizations under the hood, and so I would avoid calling an NSArray
initializer until after you have all your data ready to go.
You are not creating a sub-class of NSMutableArray, just adding a category, therefore calling [super init] will call the NSArray and not the NSMutableArray initializer, whetever it does which i would call just in case it does something important.
Also, as Ravin mentioned, setting self = without calling [self release] first will leak the previous object, which was returned from the alloc call one level up in the call stack.
This is what you should do:
-(id)initWithNullCapacity:(int)capacity
{
self = [self initWithCapacity:capacity];
if (self)
{
for (int i = 0; i < [self count]; i++)
{
[self addObject:[NSNull null]];
}
}
return self;
}
Yes it will because at first line
self = [super init];
you are creating one object(self
) and at self = array;
you are de-referencing self
and reassigning it. so earlier value is in leak.
-(id)initWithNullCapacity:(int)capacity
{
self = [super init];
if (self) {
for (unsigned i = 0; i < capacity; i++)
{
[self addObject:[NSNull null]];
}
}
return self;
}
should do the job
精彩评论