一 Object—C内存管理基本原理
Objective-C的内存管理机制与.Net/Java那种全自动的垃圾回收机制是不同的,它本质上还是C语言中的手动管理方式,只不过稍微加了一些自动方法。我从网上找了些资料,自己也总结了几点如下:
1 Objective-C的对象生成于堆之上,生成之后,需要一个指针来指向它。
ClassA *obj1 = [[ClassA alloc] init];
2 下面代码中是否出现错误?
int *p = 0x0001;
//NSLog(@"%d", *p);
int *q = malloc(sizeof(int));
*q = 4;
free(q);
NSLog(@"%d", *q);
*q = 5;
NSLog(@"%d",*q);
我们需要运用什么方法才能防止野指针的现象出现?
House *House3 = [[House alloc]init];
NSLog(@"%lu",[House3 retainCount]);
House *House2 = [House3 retain];
NSLog(@"%lu",[House2 retainCount]);
NSLog(@"%lu",[House3 retainCount]);
House *House1 = [House3 retain];
NSLog(@"%lu",[House1 retainCount]);
[House1 release];
House1 = nil;
[House2 release];
House2 = nil;
[House3 autorelease];
NSLog(@"%lu",[House3 retainCount]);
防止野指针现象 把release的指针进行nil处理。
3
ClassA *obj1 = [[ClassA alloc] init]; //对象生成时,retain count = 1
[obj1 release]; //release使retain count减1,retain count = 0,dealloc自动被调用,对象被销毁
我们回头看看刚刚那个无效指针的问题,把dealloc改成release解决了吗?
ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj1 hello]; //输出hello
[obj1 release]; //retain count = 0,对象被销毁
[obj2 hello];
[obj2 release];
4 Objective-C指针赋值时,retain count不会自动增加,需要手动retain。
ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //输出hello
[obj1 release]; //retain count = 2 – 1 = 1
[obj2 hello]; //输出hello
[obj2 release]; //retain count = 0,对象被销毁
问题解决!注意,如果没有调用[obj2 release],这个对象的retain count始终为1,不会被销毁,内存泄露。(1-4可以参考附件中的示例程序memman-no-pool.m)
这样的确不会内存泄露,但似乎有点麻烦,有没有简单点的方法?见下一条。
5
5.1
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 但无需调用release
5.2
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //输出hello
//对于obj1,无需调用(实际上不能调用)release
[obj2 hello]; //输出hello
[obj2 release]; //retain count = 2-1 = 1