My code seems to be leaking when using C arrays and I'm not sure why.
/* LeakyClass.m */
@property (nonatomic, assign) char **array1;
@property (nonatomic, assign) id __strong *array2;
@property (nonatomic, assign) unsigned short currentDictCount;
//...
- (id)initWithCapacity:(unsigned short)capacity
{
if ((self = [super init])) {
_array1 = (char **)calloc(sizeof(char*), capacity); //Leak
_array2 = (id __strong *)calloc(sizeof(id), capacity); //Leak
}
return self;
}
- (void)dealloc {
free(_array1);
free(_array2);
_array1 = NULL;
_array2 = NULL;
}
- (void)addObjectToArray2:(id)object andCharToArray1:(char *)str
{
[self array2][[self currentDictCount]] = object;
[self array1][[self currentDictCount]] = str;
[self setCurrentDictCount:[self currentDictCount] + 1];
}
@end
I call LeakyClass
with this:
/* OtherClass.m */
LeakyClass *leaky = [[LeakyClass alloc] initWithCapacity:20];
[leaky addObjectToArray2:object andCharToArray1:"1"]; // Leak
[leaky addObjectToArray2:@"example" andCharToArray1:"2"]; /Leak
[leaky addObjectToArray2:[NSURL URLWithString:exampleString] andCharToArray1:"3"]; /Leak
Instruments are pointing to each of the values passed onto the LeakyClass
to add to array 1. In this example, object
, @"example"
and [NSURL URLWithString:exampleString]
. Instruments is also pointing to the calloc
s for _array1
and _array2
but I free both of them in dealloc
.
Am I missing something?
First of all using __strong
with an id
pointer is meaningless, ARC will try to send the release
, retain
etc messages to the pointer, not to each of you objects (given your current implementation it doesn't even know how many objects you dynamically allocated) , so, in short terms, you're the same with or without it. As for the leak, try to free your pointers before alloc.
Anyways, as others mentioned, why not use NSArray
or/and NSDictionary
?
Edit following the comments below:
When I said "you're the same with or without it" I meant, it will not help you in any way with your memory management, it's meaningless. However, you have to have an ownership qualifier, so just removing it will end up in an error (as you reported). You should use
@property (nonatomic, assign) id __unsafe_unretained *array2;
As for your memory problem, did you tried to free
before alloc
? What happens if initWithCapacity:
gets called twice, I know you won't call it twice, but there's no guarantee for instruments to know.
Also here are the specs for you to understand better ARC and all the qualifiers.