为什么这个代码泄露在仪器上?

时间:2011-04-10 06:00:26

标签: iphone objective-c memory-management memory-leaks retaincount

我正在对乐器进行一些内存分析,我觉得我的代码似乎正在进行适当的内存管理。然而,仪器确信我正在泄漏,我无法弄清楚如何使泄漏消失。

在我的Event.h中,我有。


@property (nonatomic, copy) NSString *organizer;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, retain) NSDate *startTime;
@property (nonatomic, retain) NSDate *endTime;
@property (nonatomic, copy) NSString *coverCharge;
@property (nonatomic, copy) NSString *ageLimit;
@property (nonatomic, copy) NSString *dressCode;
@property (nonatomic, copy) NSString *venueName;
@property BOOL attendingFlag;

他们全部以dealloc发布


- (void) dealloc {
    [type release];
    [organizer release];
    [startTime release];
    [endTime release];
    [coverCharge release];
    [ageLimit release];
    [dressCode release];
    [venueName release];
    [super dealloc];
}   

在我的工厂课上,我有


-(Event*) getEvent:rs {
    Event *event = [[Event alloc] init];
    event.objId = [NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_ID_FIELD]];
    event.name= [rs stringForColumn:DATABASE_EVENT_NAME_FIELD];
    event.organizer = [rs stringForColumn:DATABASE_EVENT_ORGANIZER_FIELD];
    event.type = [rs stringForColumn:DATABASE_EVENT_TYPE_FIELD];
    event.desc= [rs stringForColumn:DATABASE_EVENT_DESCRIPTION_FIELD];
    event.venueName = [rs stringForColumn:DATABASE_EVENT_VENUE_NAME_FIELD];
    event.coverCharge= [rs stringForColumn:DATABASE_EVENT_COVER_CHARGE_FIELD];
    event.dressCode = [rs stringForColumn:DATABASE_EVENT_DRESS_CODE_FIELD];
    event.ageLimit = [rs stringForColumn:DATABASE_EVENT_AGE_LIMIT_FIELD];
    event.region = [[[Region alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_REGION_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_REGION_NAME_FIELD]] autorelease];
    event.community = [[[Community alloc] initWithIdAndName:[NSNumber numberWithInt:[rs intForColumn:DATABASE_EVENT_COMMUNITY_ID_FIELD]] name:[rs stringForColumn:DATABASE_EVENT_COMMUNITY_NAME_FIELD]] autorelease];
    event.address = [rs stringForColumn:DATABASE_EVENT_ADDRESS_FIELD];
    event.address2 = [rs stringForColumn:DATABASE_EVENT_ADDRESS2_FIELD];
    event.city = [rs stringForColumn:DATABASE_EVENT_CITY_FIELD];
    event.state = [rs stringForColumn:DATABASE_EVENT_STATE_FIELD];
    event.zip = [rs stringForColumn:DATABASE_EVENT_ZIP_FIELD];
    event.country = [rs stringForColumn:DATABASE_EVENT_COUNTRY_FIELD];
    event.phone = [rs stringForColumn:DATABASE_EVENT_PHONE_FIELD];
    event.webpage = [rs stringForColumn:DATABASE_EVENT_WEBPAGE_FIELD];

    return [event autorelease];
}

你可能会注意到我在事件上设置了比我上面提到的更多的属性,那是因为我有事件扩展另一个更通用的实体。我甚至没有发布该代码的原因是因为根据工具,我甚至泄漏了Event类本身的setter。

Instruments抱怨Event alloc上有一个泄漏,而getEvent选择器中的每一行都有一个泄漏。 rs是来自库(FMDB)的结果集对象,我正在整个应用程序中使用它,这似乎是检测到这些泄漏的唯一实体,所以我很确定这不是问题。我最近实际上已将同一个库用于另一个项目,并且没有泄漏,因此我将其作为泄漏源消除了。

(a)当我返回时,我显然是自动释放事件对象。

(b)我的所有setter都获得了自动释放的对象,所以我只是按照目标c的内存管理文档的建议增加了保留计数。

知道为什么分配线和它后面的几乎每一行都可能泄漏?

1 个答案:

答案 0 :(得分:1)

答案是其他地方的代码保留了您的Event对象。泄漏只能显示泄漏的内存是在哪里创建的,Leaks无法显示应该编写的代码,以便在创建后正确释放对象!

其他行都标记为泄漏,因为Event对象正在泄漏。

要做的是在Leaks之外添加Allocations工具,并确保将其设置为“记录参考计数”(时间图上的Allocations栏中的little(i))。然后启动你的应用程序,观察泄漏。然后选择Allocations工具,选择“created and still living”,然后查找仍然存在的Event对象。

然后单击地址旁边的箭头,您将获得该对象的每个保留和释放的列表。您通常可以从中找出保留该对象的内容,该对象应该稍后释放但不会。