0

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

在我的 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 扩展了另一个更通用的实体。我什至没有发布该代码的原因是因为根据工具,我什至泄漏了 Event 类本身的设置器。

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

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

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

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

4

1 回答 1

1

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

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

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

Then click on the arrow next to the address, and you'll get a list of every retain and release for that object. You can usually figure out from that what retained the object that should have also released it later but did not.

于 2011-04-10T06:08:15.407 回答