启用ARC时泄漏

时间:2012-12-06 13:18:04

标签: objective-c automatic-ref-counting free memory-leaks calloc

使用C数组时,我的代码似乎泄漏了,我不知道为什么。

/* 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

我打电话给LeakyClass

/* 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

乐器指向传递到LeakyClass的每个值以添加到数组1.在此示例中,object@"example"[NSURL URLWithString:exampleString]。乐器也指向calloc_array1的{​​{1}},但我在_array2中释放了它们。

我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

malloc / calloc内存未被引用计数,您强烈决定何时分配它以及何时释放它。将该指针设置为NULL不会释放它,使用free:

free(_array1); 
free(_array2);

这就像一个dealloc消息,但是处理原始内存,而不是objective-c类 如果要在垃圾收集器中包含原始内存,请使用NSData包装它:

@property (nonatomic,strong) NSData* wrapper1;
@property (nonatomic,strong) NSData* wrapper2;

包裹数据:

wrapper1= [NSData dataWithBytesNoCopy: _array1 length: capacity*sizeof(char*) freeWhenDone: YES];
wrapper2= [NSData dataWithBytesNoCopy: _array2 length: capacity*sizeof(id) freeWhenDone: YES];

并且不要释放它,而是设置为nil wrapper1和wrapper2.But即使没有覆盖dealloc方法,你也可以在对象死后释放所有内存。

答案 1 :(得分:0)

首先使用带有__strong指针的id毫无意义,ARC会尝试将releaseretain等消息发送到指针,而不是每个你的对象(鉴于你当前的实现它甚至不知道你动态分配了多少个对象),所以,简而言之,无论有没有它都是一样的。至于泄漏,请尝试在alloc之前释放指针。

无论如何,正如其他人提到的,为什么不使用NSArray或/和NSDictionary

修改以下评论:

当我说“无论有没有它都是一样的”我的意思是,它对你的记忆管理没有任何帮助,这是没有意义的。但是,您必须拥有所有权限定符,因此只需删除它就会出现错误(如您所报告的那样)。你应该使用

@property (nonatomic, assign) id __unsafe_unretained *array2;

至于你的记忆问题,你在free之前尝试alloc了吗?如果initWithCapacity:被调用两次会发生什么,我知道你不会把它叫两次,但是不能保证仪器可以知道。

此外,here是您了解更好的ARC和所有限定符的规范。