简体   繁体   中英

Why is this code leaking on instruments?

I'm doing some memory profiling on instruments and I feel like I have code that seems to be doing proper memory management. However, instruments is convinced that I'm leaking and I can't figure out how to make the leak go away.

In my Event.h I have.


@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;

They're all released in dealloc


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

And in my factory class, I have


-(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];
}

You may notice that I'm setting more attributes on the event than I have mentioned above and that's because I have Event extending another Entity which is more generic. The reason I didn't even post that code is because according to instruments, I'm leaking on even the setters for the Event class itself.

Instruments complains that there is a leak on the Event alloc and another one on every line in the getEvent selector. The rs is a resultset object from a library (FMDB) that I'm using all over the app and this seems to be the only entity where these leaks are detected so I'm pretty sure that's not the issue. I've actually used this same library for another project recently, and there were no leaks caused by it so I've eliminated it as the source of the leak.

(a) I'm clearly autoreleasing the event object when I return it.

(b) All my setters are getting autoreleased objects so I'm only increasing the retain count as recommended by the memory management docs for objective c.

Any idea why the alloc line and almost every line following it may be leaking?

The answer is that code elsewhere is retaining your Event object. Leaks can only show you where memory that has been leaked was created, Leaks cannot show you the code that should have been written to correctly release the object after creation!

The other lines are all marked as leaks because the Event object is leaking.

The thing to do is to add the Allocations instrument in addition to Leaks, and make sure it's set to "record reference counts" (little (i) in the Allocations bar on the time graph). Then start your app, observe the leak. Then select the Allocations tool, select "created and still living", and look up Event objects still around.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM