Transcript

Objective C/C++

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

LOCAL OBJECTSMemory and resource management

C• System language• Portable assembler

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

C++• Delete is for implementing libraries!

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

• No difference between memory and other resource types

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

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

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}

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

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

LONG-LIVED OBJECTSMemory and resource management

Approaches

Ownership graph Garbage collector

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

Approaches• You must prove the graph is acyclic!

Approaches• What is more scary than memory leak?

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

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

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

Objective-C• Subtle differences

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

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; // ???}

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

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!

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

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

Objective-C++• Retain cycles

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

@end

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

@end

Retain cycles• Can compiler find them?

• Can runtime find them?

• Can tools find them?

• Is there a simple approach to avoid them?

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?

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?

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?

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.

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

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

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}

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

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

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 );}

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 );}

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];! });}

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

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

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

Do not worry!This is also easy!

top related