0

看起来我不了解Objective C中的内存管理......叹息。

我有以下代码(请注意,在我的情况下,placemark.thoroughfare并且placemark.subThoroughfare都填充了有效数据,因此两个 -if条件都是TRUE

item绑定到一个ManagedObjectContext. item诸如此类的托管变量place具有使用@dynamic. 因此,声明是

@property (nonatomic, retain) NSString *place;
@dynamic place;

稍后在代码中,在 ReverseGeocoderDelegate 中,我访问它:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {

if (placemark.thoroughfare) {
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];        
} else {
    [item.place release];
    item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}

如果我没有item.place在代码中的标记位置释放,Instruments 会在那里发现内存泄漏。如果我这样做了,一旦我尝试item.place在违规方法之外访问,程序就会崩溃。

有任何想法吗?

4

2 回答 2

2

首先,我会改变这样的逻辑:

NSString *newPlace = nil;

if (placemark.thoroughfare && placemark.subThoroughfare) {
    newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
    if (placemark.thoroughfare) {
        newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
    }
    else {
        newPlace = @"Unknown Place";
    }
}

item.place = newPlace;    // Either nil of valid string can be assigned to

许多人不推荐使用 release 来简单地重新初始化指针。如果是为了节省一些内存,您不必这样做。

您之前的逻辑确实释放了两次。release 最初所做的只是递减retainCount。如果为 0,则对象被释放。retainCount对象在其为 0之前不会被释放。

假设您的项目具有属性retain并且由于stringWithFormat:返回autoreleased字符串,所以在第二次发布时,您试图发布autoreleased无论如何都会发生的事情。

多次清除对象的最佳方法是简单地分配nil给它。

于 2011-01-16T13:21:20.687 回答
1

一个起点是重新阅读有关属性的信息,因为您不需要在任何地方执行“[item.place release]”。所以你可以删除它们。运行时创建的用于启用该属性的动态代码会自动处理释放之前分配给它的任何内容。

此外,它[NSString stringWithFormat:...创建了一个自动释放对象(不确定您是否知道:-),这意味着如果您手动管理变量(不是属性)的内存,那么您将不得不保留/释放它。但是因为您使用的是属性,所以您没有。

我不明白为什么仪器会发现内存泄漏。也许一些更高的代码与它有关。例如,如果你去了item.place = [NSString alloc] initWith...];,那么我认为你会需要它。

我怀疑崩溃是因为版本导致保留计数为零并触发 exec 错误访问错误。

希望有帮助。

于 2011-01-16T11:48:29.550 回答