这里有内存泄漏吗?

时间:2010-05-31 17:38:13

标签: objective-c memory-leaks

请在代码中查看我的评论:

-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{        
    [super init];
    coordinate = c;
    NSDate *today = [NSDate date];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterLongStyle];

    NSString* formattedDate = [NSString stringWithFormat:@"%@ %@",
                           [dateFormatter stringFromDate:today], t];


    [self setTitle:formattedDate]; //Why does the app crash when I try and release formattedDate?  I have after all passed its reference to the title property?


    [dateFormatter release]; //I need to release the dateformatter because I have finished using it and I have not passed on a reference to it

    return self;
}

3 个答案:

答案 0 :(得分:6)

不,看起来不错。 stringWithFormat返回一个自动释放的对象 - 除非你retain它没有,否则你不拥有它,所以你不能释放它。您自己分配了dateFormatter,因此 拥有它并且必须release

(参见object ownership documentation和8个非常相似的SO问题。这必须是在这里显着增加的头号目标问题。)

修改:实际上,看一下你的评论,这里有一个非常轻微的更微妙的问题,虽然结果是相同的(实际上强调了所有权的观点)

当您将字符串传递给setTitle时,可以 retain字符串本身,在这种情况下,此处调用release可能不会导致崩溃立即。但是,你仍会过度释放,最终它会咬你。只是更难以找到问题的原因。

碰巧,setTitle制作副本而不是保留你的副本。这在NSString属性中很常见。一个原因是您可能会传递NSMutableString,然后在稍后的某个时间点随机更改它可能会搞砸接收器。私人复制更安全。作为奖励,它会立即暴露您的过度释放,并允许您轻松修复它。

无论如何,重点是:只有release你知道自己拥有的东西。如果您刚刚将它传递给其他对象,则该对象有责任处理它是否拥有它,而不是您的。

答案 1 :(得分:1)

您似乎对保留和释放工作有一些根本的误解。你说:

  1. “当我尝试发布formattedDate时,为什么应用程序崩溃?我毕竟已经将它的引用传递给title属性”

  2. “我需要发布dateformatter,因为......我还没有传递对它的引用”

  3. 您是否传递某个引用与您是否负责释放它无关。 memory management rules决定你是应该保留还是释放一些东西,它们几乎与传递引用无关。你应该阅读那份文件,因为它非常基础而且并不是那么难。一旦你明白了,所有关于这类事情的问题都将消失。

    简言之,您拥有一个对象,并且如果您是通过new alloccopy方法获得的,或者retain它。对于NSDateFormatter,您可以从alloc获取它,因此您必须将其释放。对于字符串,这些都不是真的,因此您必须发布您不拥有的此对象。

答案 2 :(得分:0)

略有不相关,但......

ObjC中的初始化器应该看起来像

- (id)init;
{
    self = [super init];
    if (self == nil)
        return self;
    ...
    return self;
}

这允许超类返回替换。这是ObjC的非常先进的用法,但坚持这种模式是一个好习惯。

ADC: Allocating and Initializing Objects的更多信息。