Objective C Memory Management

Post on 21-Oct-2014

6,195 views 1 download

Tags:

description

iOS 3 and iOS 4 Memory Management Tips and Tricks

transcript

Objective-C Memory Management

by Ahmed Magdy

Introduction

Objective-C :

Is a strict superset of C

Is an OOP version of C using message passing.

Uses a variation of GCC and GDB

Has dynamic and static memory allocation

Uses “Reference Counting” to manage memory in iOS.

OUTLINE

Reference counting Object Ownership Auto-release pools Conventions Properties in Objective-C Rules of Thumb Common mistakes Optimizations

Reference Counting

New object created with reference count=1

Send retain/release message to increase/decrease reference count

Object deallocated automatically when reference count becomes 0

Object ownership

Any object may have one or more owner

Object’s creator becomes its 1st owner

Other owners must retain object

Owner is responsible for releasing object

Owner must never destroy object directly

Object without owners are deallocated automatically

Weak references used to avoid infinite retain loops

Auto-release Pools

What is an Autorelease pool?

Use autorelease method when you don’t want to own the object

autorelease mean “Release later”

Every thread should have it’s own pool

Auto-release pool example

@implementation Person-(void)startPlayWithPets { [NSThread detachNewThreadSelector:@selector(play) toTarget:self withObject:nil];}-(void)play { // without pool every autoreleased object will leak memory NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // safe accessor returns autoreleased object, added to thread’s autorelease pool NSArray* petsToPlay = [self pets] ; BOOL allPetsAreHappy = NO; while(! allPetsAreHappy) { ... // some code, that may create autoreleased objects } [pool release]; // or [pool drain]; memory is freed, petsToPlay released as well}@end

Conventions

To create an object and be the first owner of it, use a method that has one of these in its name:

- alloc- new- copy- mutableCopy

If we use properties and convenience constructors we do not take ownership of the object.

- Convenience Constructors (Factory Pattern) like: stringWithFormat, imageWithData, imageWithContentsOfFile, stringWithContentsOfFile

Properties in Objective-C

Writability (readonly, readwrite)

Setter semantic (assign, copy, retain)

Atomicity (atomic, nonatomic)

Declaration:@property (writability, setter, atomicity) type name;@synthesize name=ivarName;

Usage:object.propertyName = newValue;value = object.propertyName;

Properties in Objective-C example 1

@property (nonatomic, retain) NSString* name;@synthesize name;

// is equivalent to a pair of methods-(NSString*)name {

return [[name retain] autorelease];}-(void)setName:(NSString*)aName {

if (name != aName) {[name release];name = [aName retain];

}}

Properties in Objective-C example 2

@property (atomic, copy) NSString* name; // equivalent to -(NSString*)name {

NSString* retVal=nil;@synchronized(self)

retVal = [[name retain] autorelease];return retVal;

}-(void)setName:(NSString*)aName {

@synchronized(self) if (name != aName) {

[name release];name = [aName copy];

}}

Rules of Thumb

1. Use autorelease for temporaries

2. Retain & release members

3. Use properties to get correct setters

4. Break rule 2 to avoid retain loops

Use autorelease for temporaries

- (void) foo { NSString* s = [NSString string];

Or

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

}

Retain & release members

@interface Bar {NSString* _name;

}@end- (id) init {

if (self = [super init]) {_name = [[NSString alloc] init];

}return self;

}- (void) dealloc {

[_name release];[super dealloc];

}

Use properties to get correct setters

@interface Bar {NSString* _name;

}@property(retain) NSString* name;@end

@implementation@synthesize name = _name;- (void) dealloc {

[_name release]; // still important because of _name[super dealloc];

}@end

Break rule 2 to avoid retain loops

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

Common mistakes

Premature delete Double-deletion No retain/release balance [self release] Reassign of pointer without releasing old value Overriding retain & release methods

Premature Deletion

- (void)init { if (self = [super init]) {

_foo = [NSString string];}

}

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

}

Double-deletion

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

... [pool release] or [pool drain];

- (void)dealloc {[_foo release]; // retain count -1[super dealloc];

}

No retain/release balance

Causing either:

A memory leak, if the retain are greater than the releases

or

A dangling pointer, if the releases are greater than the retains. (Bad Access Error or accessing an illegal piece of memory)

[self release]

- (void) someMethod {_name = @”the name”;_message = [[[NSString alloc] initWithFormat:

@”my name is: ”, _name] autorelease];[self release];NSLog(_message); // error, if self is deallocated

}

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

}

Reassign of pointer without releasing old value

- (void) leak {NSString *name = [NSString alloc]

initWithFormat:@”%@”, @”Ahmed”];name = @”Ali”;// the value @”Ahmed” is still there so there is a

memory leak}

Overriding retain & release methods

Some developers tend to override retain and release methods.

They have to be very careful or else they may cause a memory leak or a dangling pointer.

Optimizations

Use C structures instead of classes

Keep immutable objects

Release now instead of autorelease if possible

Nested Autorelease pools

Use UIKit recommendations

Summary

Reference counting Object Ownership Auto-release pools Conventions Properties in Objective-C Rules of Thumb Common mistakes Optimizations

Thank you