【前情提要】
內存分配地址:棧區地址最高,堆區次之,常量區再次之
1、NSString等Foundation框架中類的內存管理
1)如果你需要的字符串在常量池中已經存在,則不會分配內存空間
【使用字符串的時候】@”“,stringWithString, alloc initWithString都是在常量區
【常量區的對象引用計數是無符號的最大值,如果用%ld輸出是-1,用retain和release是沒有用的】
【使用initWithFormat時字符串在堆區,前面有alloc時需要release,如果沒有系統會自動消滅,不用理會】
例如:
@autoreleasepool {
int a = 1;//棧區
/*如果你需要的字符串在常量池中已經存在,則不會分配內存空間
【使用字符串的時候】@”“,stringWithString, alloc initWithString都是在常量區
*/
NSString *str1 = @"abc";//常量區
NSString *str2 = [NSString stringWithString:@"abc"];//常量區
NSString *str3 = [[NSString alloc] initWithString:@"abc"];//常量區
/*【使用initWithFormat時字符串在堆區,前面有alloc時需要release,如果沒有系統會自動消滅,不用理會】
*/
NSString *str4 = [NSString stringWithFormat:@"abc"];//堆區
NSString *str5 = [[NSString alloc] initWithFormat:@"abc"];//堆區
NSLog(@"a = %d,address = %p, retainCount = %lu",a,&a, str1.retainCount);
NSLog(@"str1 = %@,address = %p, retainCount = %lu",str1,str1, str1.retainCount);
NSLog(@"str2 = %@,address = %p, retainCount = %lu",str2,str2, str2.retainCount);
NSLog(@"str3 = %@,address = %p, retainCount = %lu",str3,str3, str3.retainCount);
NSLog(@"str4 = %@,address = %p, retainCount = %lu",str4,str4, str4.retainCount);
NSLog(@"str5 = %@,address = %p, retainCount = %lu",str5,str5, str5.retainCount);
}
打印結果:
2015-10-06 16:12:59.962 MRCDemo[2146:303] a = 1,address = 0x7fff5fbff93c, retainCount = 18446744073709551615
2015-10-06 16:12:59.964 MRCDemo[2146:303] str1 = abc,address = 0x1000023a8, retainCount = 18446744073709551615
2015-10-06 16:12:59.965 MRCDemo[2146:303] str2 = abc,address = 0x1000023a8, retainCount = 18446744073709551615
2015-10-06 16:12:59.965 MRCDemo[2146:303] str3 = abc,address = 0x1000023a8, retainCount = 18446744073709551615
2015-10-06 16:12:59.966 MRCDemo[2146:303] str4 = abc,address = 0x100109c80, retainCount = 1
2015-10-06 16:12:59.966 MRCDemo[2146:303] str5 = abc,address = 0x10010a660, retainCount = 1
【疑問1】
NSString *str3 = [[NSString alloc] initWithString:@"abc"];爲什麼這樣也是alloc,但是卻是在常量區。因爲這種用法被Xcode特殊處理過。同樣地NSString *str2 = [NSString stringWithString:@"abc"];這種用法也是在常量區的。
【疑問2】
NSString *str4 = [NSString stringWithFormat:@"abc"];這種用法創建的字符串對象也是在堆區,但是一旦使用release就會掛掉。因爲,這種是由系統自動清理的,不需要手動release。而NSString *str5 = [[NSString alloc] initWithFormat:@"abc"];這種因爲手動調用了alloc方法,因此需要手動release
【危險用法】:使用retainCount作爲循環條件的判斷
while ([str2 retainCount] > 0) {
[str5 release];
}
這種做法有可能導致死循環,不要使用retainCount作爲循環判斷條件