Leaks & Zombies

Post on 06-Jul-2015

4.737 views 3 download

description

A BarCamp presentation about iPhone memory management programming. Teemu Kurppa gave this at MobileDevCamp Helsinki (http://MobileDevCamp.fi)

Transcript of Leaks & Zombies

&ZombiesLeaks

Teemu KurppaCo-Founder, Huikea.com

A quick intro to iPhonememory management

BasicsNSString* s = [[NSString alloc] init]; ➊[s release]; ⓪

NSString* s = [[NSString alloc] init]; ➊[s retain]; ➋[s release]; ➊[s release]; ⓪

Basics

AutoreleaseNSString* s = [[[NSString alloc] init] autorelease]; ➊

NSAutoreleasePool* pool = [[NSAutoreleasePool] alloc] init];

...

NSString* s = [[[NSString alloc] init] autorelease]; ➊ ...

[pool release]; ⓪

Autorelease

NSString* s = [NSString string]; ➊[pool release]; ⓪

why? because:

@implementation NSString

+ (NSString*)string { return [[[NSString alloc] init] autorelease];

}

@end

Factory methods

- (void)setFoo:(Bar*)aFoo { [_foo release]; _foo = [aFoo retain]; // Incorrect, why?}

An incorrect setter

- (void)setFoo:(Bar*)aFoo { if (aFoo != _foo) { [_foo release]; _foo = [aFoo retain]; }}

A correct setter

- (void)setFoo:(Bar*)aFoo { [_foo autorelease]; _foo = [aFoo retain];}

A correct setter

4 Rules of Thumb1 Use autorelease for temporaries2 Retain & release members3 Use properties to get correct setters4 Break rule 2 to avoid retain loops

- (void) foo { NSString* s = [NSString string]; ➊ or NSString* s = [[[NSString alloc] init] autorelease]; ➊}

Rule 1: Use autorelease for temporaries

@interface Bar { NSString* _name;}@end

- (id) init { if (self = [super init]) { _name = [[NSString alloc] init]; } ➊ return self;}

- (void) dealloc { [_name release]; ⓪ [super dealloc];}

Rule 2: Retain & release members

@interface Bar { NSString* _name;}@property(retain) NSString* name;@end

@implementation@synthesize name = _name;

- (void) dealloc { [_name release]; // still important! [super dealloc];}

Rule 3: Use properties to get correct setters

@interface Bar { id _delegate;}@property(assign) id delegate; // Note: not retain!@end

@interface Foo { Bar* _bar;}@end

in Foo:

_bar = [[Bar alloc] init];_bar.delegate = self;

Rule 4: Break rule 2 to avoid retain loops

What about bugs?

- (void)init { if (self = [super init]) { _foo = [[NSString alloc] init];

➊}

- (void)dealloc { [super dealloc];}

A leak

- (void)init { if (self = [super init]) { _foo = [NSString string];

}

- (void)foo {NSLog(@”Foo is %@”, _foo);

}

Premature delete

- (void) f { Bar* bar = [NSString string];

➊ _foo = bar;}

... [pool release]; // ⓪

- (void)dealloc { [_foo release]; !!! -1 [super dealloc];}

Double-deletion

NSZombieEnabled

Zombies to help

NSZombieEnabled

Zombies to help

by lunchtimemama http://www.flickr.com/photos/lunchtimemama/97685452/sizes/o/

by Rachel Cobcroft http://www.flickr.com/photos/felix42/453311029/sizes/o/