Objective-c memory

58
Objective C/C++ Работа с памятью без использования Instruments

Transcript of Objective-c memory

Page 1: Objective-c memory

Objective C/C++

Работа с памятью без использования Instruments

Page 2: Objective-c memory

LOCAL OBJECTSMemory and resource management

Page 3: Objective-c memory

C• System language• Portable assembler

Page 4: Objective-c memory

C• Memory management - C example

static bool check_memory(){! Something * a = (Something *)malloc( sizeof(Something) );! if( !a )! ! return false;! do_something(a);! if( some_condition(a) )! {! ! free(a);! ! return true;! }! // Lots of code! free(a);! return false;}

Page 5: Objective-c memory

C• Resource management - C example

static bool check_file(const char * name){! FILE * fs = fopen(name, "rb");! if( !fs )! ! return false;! int first = fgetc(fs);! if( first == 32 )! {! ! fclose(fs);! ! return true;! }! // Lots of code! fclose(fs);! return false;}

Page 6: Objective-c memory

C• Resource management - C example

static bool check_file(const char * name){! FILE * fs = fopen(name, "rb");! if( !fs )! ! return false;! int first = fgetc(fs);! if( first == 32 )! {! ! fclose(fs);! ! return true;! }! // Lots of code! fclose(fs);! return false;}

Page 7: Objective-c memory

Java• Memory management example

static public boolean check_memory() { Something a = new Something(); a.do_something(); if( a.some_condition() ) return true; // Lots of code return false; }

Page 8: Objective-c memory

Java• Resource management example

static public boolean check_file(String name) throws Exception { FileInputStream fs = new FileInputStream(name); int first = fs.read(); if( first == 32 ) return true; // Lots of code return false; }

Page 9: Objective-c memory

Java• Resource management example

static public boolean check_file(String name) throws Exception { FileInputStream fs = new FileInputStream(name); int first = fs.read(); if( first == 32 ) return true; // Lots of code return false; } static public void delete_if_bad(String name) throws Exception { if( !check_file(name) ) new java.io.File(name).delete(); }

Page 10: Objective-c memory

Java• Resource management - with finally

static public boolean check_file2(String name) throws Exception { FileInputStream fs = null; try { fs = new FileInputStream(name); int first = fs.read(); if( first == 32 ) return true; // Lots of code return false; } finally{ if( fs != null ) fs.close(); } }

Page 11: Objective-c memory

Java• Resource management - with catch

static public boolean check_file3(String name) throws Exception { FileInputStream fs = null; try { fs = new FileInputStream(name); int first = fs.read(); if( first == 32 ) return true; // Lots of code } catch(Exception e) {} try { if( fs != null ) fs.close(); } catch(Exception e) {} return false; }

Page 12: Objective-c memory

C#• Memory management example

static public bool check_memory() { Something a = new Something(); a.do_something(); if( a.some_condition() ) return true; // Lots of code return false; }

Page 13: Objective-c memory

C#• Resource management example

static public bool check_file(String name) { using( FileInputStream fs = new FileInputStream(name) )

{ int first = fs.read(); if( first == 32 ) return true; // Lots of code

} return false; }

Page 14: Objective-c memory

C++• System language• Life without garbage collector?• Unique semantic!

Page 15: Objective-c memory

C++• Memory management - what C

developer thinks?• If I know C I already know C++!

static bool check_memory(){! Something * a = new Something;! if( !a )! ! return false;! a->do_something();! if( a->some_condition() )! {! ! delete a;! ! return true;! }! // Lots of code! delete a;! return false;}

Page 16: Objective-c memory

C++• Memory management - what C

developer thinks?• If I know C I already know C++!

static bool check_memory(){! Something * a = (Something *)malloc( sizeof(Something) );! if( !a )! ! return false;! do_something(a);! if( some_condition(a) )! {! ! free(a);! ! return true;! }! // Lots of code! free(a);! return false;}

Page 17: Objective-c memory

C++• Are there exceptions in C++?• Are they good or evil? Good!• If I do not use them?• You are allowed not to throw• But good C++ design always uses

exceptions, so you better be prepared

Page 18: Objective-c memory

C++• Memory management example

static bool check_memory(){! std::auto_ptr<Something> a( new Something );! a->do_something();! if( a->some_condition() )! ! return true;! // Lots of code! return false;}

Page 19: Objective-c memory

C++• Resource management example

static bool check_file(const std::string & name){! liba::FileInputStream fs(name);! int first = fs.read();! if( first == 32 )! ! return true;! // Lots of code! return false;}

Page 20: Objective-c memory

C++• Resource management example

static bool check_file(const std::string & name){! std::auto_ptr<liba::FileInputStream> fs( liba::create_fis(name) );! int first = fs->read();! if( first == 32 )! ! return true;! // Lots of code! return false;}

Page 21: Objective-c memory

C++• Delete is for implementing libraries!

{ std::auto_ptr<Something> a( new Something(...) ); if( ... ) return;}

• No difference between memory and other resource types

Page 22: Objective-c memory

Objective-C• Memory management - what C

developer thinks?• If I know C I already know Objective-C!

-(bool)check_memory{! Something * a = [[Something alloc] init];! if( !a )! ! return false;! [a do_something];! if( [a some_condition] )! {! ! [a release];! ! return true;! }! // Lots of code! [a release];! return false;}

Page 23: Objective-c memory

Objective-C• Memory management - what C

developer thinks?• If I know C I already know Objective-C!

static bool check_memory(){! Something * a = (Something *)malloc( sizeof(Something) );! if( !a )! ! return false;! do_something(a);! if( some_condition(a) )! {! ! free(a);! ! return true;! }! // Lots of code! free(a);! return false;}

Page 24: Objective-c memory

Objective-C• Are there exceptions in Objective-C?• Are they good or evil? Absolutely good!

-(void)parse_object:(NSDictionary *)dic {! // Lots of code! int val = [[[dic objectForKey:@"users"] objectAtIndex:0] intValue];! // Lots of code}

-(void)parse_object:(NSDictionary *)dic {! // Lots of code! NSArray * arr = [dic objectForKey:@"users"];! if( ![arr isKindOfClass:[NSArray class]] )! ! return; // But we must tell about error...! NSNumber * num = [arr objectAtIndex:0];! if( ![num isKindOfClass:[NSNumber class]] )! ! return; // But we must tell about error...! int val = [num intValue];! // Lots of code}

Page 25: Objective-c memory

Objective-C• Memory management example

-(bool)check_memory{! Something * a = [[[Something alloc] init] autorelease];! [a do_something];! if( [a some_condition] )! ! return true;! // Lots of code! return false;}

Page 26: Objective-c memory

Objective-C• Memory management example

-(bool)check_memory{! Something * a = [[[Something alloc] init] autorelease];! [a do_something];! if( [a some_condition] )! ! return true;! // Lots of code! return false;}

• Afraid of autorelease?• Just start using it!• It is widely used in Cocoa

Page 27: Objective-c memory

LONG-LIVED OBJECTSMemory and resource management

Page 28: Objective-c memory

Approaches

Ownership graph Garbage collector

Page 29: Objective-c memory

Approaches• It takes lots of CPU time to untangle this!

Page 30: Objective-c memory

Approaches• You must prove the graph is acyclic!

Page 31: Objective-c memory

Approaches• What is more scary than memory leak?

Page 32: Objective-c memory

Approaches• What is more scary than memory leak?• Dangling pointer!

Page 33: Objective-c memory

Objective-C• Retaining

@interface Something : NSObject {! Anything * a;}

@end

@implementation Something

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];

! [a release]; // [a autorelease];! a = [new_a retain];}

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

@end

Page 34: Objective-c memory

Objective-C• Retaining

@interface Something : NSObject {! Anything * a;}@property(nonatomic, retain) Anything * a;

@end

@implementation Something@synthesize a;

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];

! self.a = new_a;}

-(void)dealloc {! self.a = 0;! [super dealloc];}

@end

Page 35: Objective-c memory

Objective-C• Subtle differences

! self.a = new_a; // Call property! self->a = new_a; // Use variable! a = new_a; // ???

Page 36: Objective-c memory

Objective-C• Subtle differences

@interface Something : NSObject {! Anything * a_zlo_hren;}@property(nonatomic, retain) Anything * a;

@end

@implementation Something@synthesize a = a_zlo_hren;

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];

! self.a = new_a; // Call property! self->a = new_a; // Use variable! a = new_a; // ???}

Page 37: Objective-c memory

Objective-C• 4 lines to free the memory? Too much.

Anything * a_zlo_hren;

@property(nonatomic, retain) Anything * a;

@synthesize a = a_zlo_hren;

! self.a = 0; // In dealloc

Page 38: Objective-c memory

Objective-C++• Objective C is also C++

@interface Something : NSObject {! NSPtr<Anything> a;}

@end

@implementation Something

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];

! a = new_a;}

@end

• 4 lines go down to 1, good!

Page 39: Objective-c memory

Objective-C++• Retain cycles

@interface Something : NSObject {! Anything * a;}@property(nonatomic, retain) Anything * a;

@end

@interface Anything : NSObject {! Something * s;}@property(nonatomic, retain) Something * s;

@end

Page 40: Objective-c memory

Objective-C++• Retain cycles

@interface Something : NSObject {! Anything * a;}@property(nonatomic, retain) Anything * a;

@end

@interface Anything : NSObject {! Something * s;}@property(nonatomic, retain) Something * s;

@end

Page 41: Objective-c memory

Objective-C++• Retain cycles

@interface Something : NSObject {! Anything * a;}@property(nonatomic, retain) Anything * a;

@end

@interface Anything : NSObject {! Something * s;}

@end

Page 42: Objective-c memory

Retain cycles• Can compiler find them?

• Can runtime find them?

• Can tools find them?

• Is there a simple approach to avoid them?

Page 43: Objective-c memory

Retain cycles• Can compiler find them?Yes, soon (experimental languages).• Can runtime find them?

• Can tools find them?

• Is there a simple approach to avoid them?

Page 44: Objective-c memory

Retain cycles• Can compiler find them?Yes, soon (experimental languages).• Can runtime find them?Yes, Garbage Collector.• Can tools find them?

• Is there a simple approach to avoid them?

Page 45: Objective-c memory

Retain cycles• Can compiler find them?Yes, soon (experimental languages).• Can runtime find them?Yes, Garbage Collector.• Can tools find them?Yes, if included in test cases.• Is there a simple approach to avoid

them?

Page 46: Objective-c memory

Retain cycles• Can compiler find them?Yes, soon (experimental languages).• Can runtime find them?Yes, Garbage Collector.• Can tools find them?Yes, if included in test cases.• Is there a simple approach to avoid

them?Yes, analyze architecture.

Page 47: Objective-c memory

Objective-C• Containers always retain

@interface Something : NSObject {! NSMutableArray * a;}@property(nonatomic, retain) NSMutableArray * a;

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! Anything * new_a2 = [[[Anything alloc] init] autorelease];

! [a addObject:new_a];! [a addObject:new_a2];}

Page 48: Objective-c memory

Objective-C• If we do not want to retain?

@interface Something : NSObject {! NSMutableArray * a;}@property(nonatomic, retain) NSMutableArray * a;

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! Anything * new_a2 = [[[Anything alloc] init] autorelease];

! [a addObject:[NSValue valueWithNonretainedObject:new_a]];! [a addObject:[NSValue valueWithNonretainedObject:new_a2]];}

-(void)use_something {! Anything * aa = [[a objectAtIndex:0] nonretainedObjectValue];}

Page 49: Objective-c memory

Objective-C• What if we retain by accident?

@interface Something : NSObject {! NSMutableArray * a;}@property(nonatomic, retain) NSMutableArray * a;

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! Anything * new_a2 = [[[Anything alloc] init] autorelease];

! [a addObject:new_a]; // Someone forgot! [a addObject:new_a2]; // Someone forgot}

Page 50: Objective-c memory

Objective-C• Containers are untyped

@interface Something : NSObject {! NSMutableArray * a; // Of Anything}@property(nonatomic, retain) NSMutableArray * a; // Of Anything

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! Anything * new_a2 = [[[Anything alloc] init] autorelease];

! [a addObject:new_a];! [a addObject:new_a2];}

Page 51: Objective-c memory

Objective-C• Untyped containers are hard to prove

@interface Something : NSObject {! NSMutableArray * a; // Of Anything}@property(nonatomic, retain) NSMutableArray * a; // Of Anything

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! NSString * str = @"Hi";

! [a addObject:new_a];! [a addObject:str];}

Page 52: Objective-c memory

Objective-C++• We can use great STL containers

@interface Something : NSObject {! std::vector<Anything *> a;}

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! NSString * str = @"Hi";

! a.push_back( new_a );! a.push_back( str );}

Page 53: Objective-c memory

Objective-C++• Retain strategy is independent

@interface Something : NSObject {! std::vector< NSPtr<Anything> > a;}

@end

-(void)do_something {! Anything * new_a = [[[Anything alloc] init] autorelease];! NSString * str = @"Hi";

! a.push_back( new_a );! a.push_back( str );}

Page 54: Objective-c memory

Objective-C++• Integration is almost flawless!• Apple teams actually use C++ and STL

@interface Something : NSObject {! std::vector< id<UIActionSheetDelegate> > a;}

@end

-(void)do_something {! std::for_each(a.begin(), a.end(), ^(id<UIActionSheetDelegate> x) {! ! [x actionSheetCancel:nil];! });}

Page 55: Objective-c memory

Success• alloc-init-autorelease idiom• NSPtr or @property(retain) to manage

retain/release• Use text editor to eliminate all retain,

release• Architecture with no cycles• Typed containers (STL), so the compiler

can actually prove most of your architecture

Page 56: Objective-c memory

What we forgot?• Active objects (timers, http requests)• Parallel execution (NSOperation)

Page 57: Objective-c memory

What we forgot?• Active objects (timers, http requests)• Parallel execution (NSOperation)

Do not worry!This is also easy!