Memory management
Mi az a Memory Management
A memória kezelés egy olyan aspektusa a programozásnak, ahol az egyes objektumok életciklusát vezéreljük, felszabadítva azokat, ha már nincs rájuk szükség. Ez sok szempontból kritikus feladat, a memória egyrészt véges, mástrészt a növekvő "memory footprint" teljesítmény csökkenést okoz.
Az eddigi tapasztalatok
A c++ hoz képest a java jóval kényelmesebb! ● explicit meg kell határozni, mikor szabadítom fel a memóriát ● +1 dolog, amire figyelni kell ● sok hiba forrása, sok debug!
Ismerős fogalmak
foglalás
felszabadítás
c
malloc / calloc / stb
free
c++
new
delete
java
new
- (A legideálisabb)
static / stack / heap
std::map<std::string, int> myMapOnStack; myMapOnStack["key"] = 5; std::map<std::string, int>* myMapOnHeap = new std::map<std::string, int>(); (*myMapOnHeap)["key"] = 5;
iOS Memory Management iOS platformon a memória kezelése referencia számlált megoldással valósul meg. Ha létrehozunk vagy másolunk egy objektumot, a referencia számlálója 1 lesz. Ezután ha más objektumo(k) birtokolni szeretné(k) a létrehozott objektumot, a referencia számláló nő. (+1) Ha a birtoklól objektumok már nem tartanak igényt a létrehozott objektumra lemondanak róla, a referencia számláló csökken. (-1) Ha a referencia számláló nullára csökken az objektum felszabadul.
Objective C nyelven //retain count = 1 NSNumber* number = [[NSNumber alloc] initWithFloat:12.3f]; //az objektum birtoklása, retain count = 2 [number retain]; //objektum elengedése (birtoklás lemondása), retain count = 1 [number release]; //objektum elengedése, retain count = 0, dealloc [number release];
[someObject retainCount] SOHA ne hasznaljuk! 1. 2. 3. 4. 5. 6. 7. 8.
The absolute retain count of an object may change at any time once an object has been passed through any system API. Any subclass of any system provided class counts as “through system API”; the retain count may be impacted by implementation details. The retain count never reflects whether an object is autoreleased. Autorelease is a per-thread concept whereas retain counts are global; race condition derived hilarity can easily ensue. The retainCount method can never return 0. Some classes are implemented as singletons some of the time. Some classes may internally manipulate their retain count directly (I.e. no swizzle for you!). While retain/release are effectively thread safe, there is always a race between calling retainCount and having the actual retain count change in some other execution context.
Objective C memory management négy fő szabály ● Te birtoklod azt az objektumot, amit te hoztál létre. ● Egy objektumot birtokba vehetsz, ha azt retain-eled. ● Ha már nincs szükséged egy objektumra, a birtoklási viszonyt meg kell hogy szüntestd ● Birtoklási viszonyt nem szüntethetsz meg olyan objektumnál, amit nem te birtokolsz
Te birtoklod azt az objektumot, amit te hoztál létre. A metódusok, amik objektumokat létrehoznak tartalmazzák az alábbi kifejezéseket: alloc, new, copy, mutableCopy Student* student = [[Student alloc] init]; NSNumber* someNumber = [NSNumber new]; NSString* copyOfSomeString = [someString copy];
Egy objektumot birtokba vehetsz, ha azt retain-eled. 1 Általában két föbb eset különíthető el: 1. accessor vagy init függvény esetén birtokolni szeretnénk adott objektumot, hogy beállíthassuk egy property értékének @property (nonatomic, retain) NSString* name; - (void)setName:(NSString *)newName { [_name release]; _name = [newName retain]; }
Egy objektumot birtokba vehetsz, ha azt retain-eled. 2 2. biztosítani szeretnénk hogy az adott objektum érvényes marad adott kontextusban id problematicNumber = nil; NSMutableArray* numbers = [NSMutableArray arrayWithObjects:@5, @13, @12, nil]; problematicNumber = [numbers objectAtIndex:0]; [numbers removeObjectAtIndex:0]; NSLog(@"problematicNumebr:%d", [problematicNumber intValue]);
Ha már nincs szükséged egy objektumra, a birtoklási viszonyt meg kell hogy szüntestd
[student release];
Birtoklási viszonyt nem szüntethetsz meg olyan objektumnál, amit nem te birtokolsz
[someObjIDontOwn release];
Property-k újra @property (attrib1, attrib2) type name; retain copy
- lásd birtokba vétel - retain szabály - hasonlóképp az előzőhöz, csak nem retain-eljük, hanem egy másolatot készítüunk róla assign - sima értékadás memória management nélkül
Autorelease
Az autorelease üzenet segítségével késleltetett release üzenetet küldhetünk az objektumoknak. Ez akkor hasznos, amikor egy objektum birtoklásáról lemondunk, de nem szeretnénk, hogy az azonnal felszabaduljon.
Autorelease példa //Vegyük példának ezt a gyártófüggvényt: + (Student*)studentWithName:(NSString*)name { Student* student = [[Student alloc] initWithName:name]; return [student autorelease]; } //valahol a kódban... Student* student = [Student studentWithName:@"Vince"]; NSLog(@"sutdent name:%@", student.name); //ha birtokolni szeretnénk, küldünk neki retain üzenetet, ha nem akkor nem a mi felelőségünk a felszabadítás
Autorelease konvenció Minden olyan metódus, ami objektumot gyárt, és nincs benne az alloc, new, copy autorelese-elt objektumot ad vissza. Ez az elnevezésben is látszik: (sokszor osztályszintű metódusok) //str autorelase-elt NSString* str = [NSString stringWithFormat:@"%d", 15]; //strRetained-et birtoklom NSString* strRetained = [[NSString alloc] initWithFormat:@"%d", 15]; //tmpDict autorelase-elt NSDictionary* tmpDict = [NSDictionary dictionary]; //tmpDict-et birtoklom NSDictionary* tmpRetained = [[NSDictionary alloc] init];
Autorelease egyszerűsít A két megoldás teljesen ekvivalens, de a második egyértelműbb, könnyebb követni UIView *view = [[UIView alloc] initWithFrame:frame]; [self addSubView:view]; [view release]; UIView *view = [[[UIView alloc] initWithFrame:frame] autorelease]; [self addSubView:view];
Mikor hivódik a release?
Autorelease blokk végénél. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; //... NSString* str = [NSString stringWithFormat:@"%d", 15]; //... [pool drain];
Mikor nem érdemes használni autorelease-t ? nagyon! szélsőséges példa, de előfordulhat... - (void)someMethod { for (int i = 0; i < 1000000; i++) { id tempObject = [[[SomeClass alloc] init] autorelease]; //... } }
Ahoz, hogy a memory management működjön...
Mindenkinek be kell tartania a szabályokat és követnie a konvenciókat. A rendelkezésre álló könyvtárak, keretrendszerek mind feltételezik ezek teljes megértését és használatát
ARC
Automatic Reference Counting...
ARC
"Automatic Reference Counting (ARC) is a compilerlevel feature that simplifies the process of managing the lifetimes of Objective-C objects. Instead of you having to remember when to retain or release an object, ARC evaluates the lifetime requirements of your objects and automatically inserts the appropriate method calls at compile time."
ARC használata
Az ARC bevezetésével egy két megszorítás is jött. Például a klasszikus management metódusok nem hívhatók (retain, release, autorelase) http://developer.apple. com/library/ios/#releasenotes/General/WhatsNewIniOS/Arti cles/iOS5.html
ARC property változások Két referencia típust különböztet meg. strong / weak A strong tökéletesen analóg a retain-es "régi" verzióval A weak egy intelligens assign. (ha a objektum melyreől referenciánk van felszabadul autómatikusan nil értéket kap a property!)