内存管理的原则 : 1:如果对象有人在使用,那么就不应该回收。如果你想使用这个对象,就应该让这个对象retain一次。如果你 不想用这个对象了,就应该让这个对象release一次。 2:谁创建 谁release (哪个对象创建了空间,那个对象就release) 3:谁retain 谁release (哪个对象的空间引用计数器retain了,哪个对象就release) 内存管理研究的内容: 1:野指针:定义的指针变量没有初始化或者是指向的空间已经被释放。 2:内存泄露:如果栈区的指针变量已经被释放了,而堆区的空间还没有释放,堆区的空间就被泄露。 单个对象的内存管理(野指针): 1:野指针错误:访问了一块坏的内存(已经被回收的不可用的内存)。 2:僵尸对象:所占内存已经被回收的对象, 僵尸对象不能再被使用。 3:空指针:对象值为空,没有指向任何东西的指针,给空指针发送消息不会报错。 nil: 表示对象的值 NIL:表示类的值 NULL:通用指针(泛型指针) [NSNull null]: 是一个对象,他用在不能使用nil的场合 (了解即可) 4: 当一个对象的空间被释放了,引用计数器为0,这个对象是僵尸对象,如果再用[对象名 retain]方法是不行的。下面举个例子: 如: Dog *d = [Dog new]; //创建一个对象,他有一个拥有者,引用计数器的值为1 [d release]; //用release方法使计数器减1, 这时的计数器为0,对象的空间被释放。 [d retain]; //对象空间已被释放,对象成为了僵尸对象,这时再retain是不合法的。 如果非要对已释放空间的对象retain,那么看下面的方法 : 如: Dog *d = [Dog new]; //创建一个对象,他有一个拥有者,引用计数器的值为1 [d release]; //用release方法使计数器减1, 这时的计数器为0,对象的空间被释放。 d = nil; // 在上一步对象空间被释放,这时的对象d指向了nil,也就是0,所以下面的retain可以执行 [d retain]; //上一步对象d指向了nil(0),计数器为0,对象有指向不是僵尸对象,多以可以执行这步。 单个对象的内存泄露问题: 情况1: // 对象创建完成开辟完内存空间后没有release,计数器为1,程序结束后内存还存在没释放 Dog *d = [[Dog alloc] init ]; return 0; 情况2: // 没有遵守内存管理的原则 Dog *d = [[Dog alloc] init ]; //创建对象 计数器为1 [d retain]; // retain(+1) 计数器为2 [d release]; // release (-1) 计数器为1 return 0; //程序结束时 计数器不为0,内存空间没有释放 情况3: // 不当的使用了nil Dog *d = [[Dog alloc] init ]; //创建对象 计数器为1 d = nil; // 把0赋值给了对象d,下面方法不会执行 [d release]; // 这一步就相当于 [nil release] return 0; //程序结束时 计数器不为0,内存空间没有释放 情况4: // 在方法中对传入的对象进行了retain 前提: -(void)run{ [d retain] //run方法中retain了一次对象d } 后续: Dog *d = [[Dog alloc] init ]; //创建对象 计数器为1 [d run] ; //对象d调用方法run 因为run方法中又给对象retain一次 所以计数器为2 [d release]; // 计数器为2,这步只release了一次,计数器为1 内存没被释放。
|