内存管理常见错误
没有改为自动管理内存
解决方法:
野指针问题
野指针异常 现象 : 可能会崩溃 ,也 可能不会崩溃 , 写到某一行代码时突然崩溃 ( 没有写任何和引用计数相关的代码 ) 原因 : 该对象的空间 , 已经被系统回收 , 不能访问没有所有权的对象解决方案 : 空间被系统回收之后 , 禁止访问 或者令其指向无效空间
过度释放
当引用计数为零时 , 系统会自动回收内存 , 我们只管理引用计数
@autoreleasepool的使用原则 @autoreleasepool { Person *person = [[ Person alloc ] init ]; //0-1
[person retain ]; //1-2 NSLog ( @"%ld" , [person retainCount ]); @autoreleasepool { [person autorelease ]; //2-1 } autorelease, 会将声明为 autorelease 的对象放入离他最近的自动释放池中 , 当自动释放池销毁时 , 会向池中的每一个对象 , 发送一个 release 消息
当该类型的对象引用计数为零时 , 系统会自动调用该类的 dealloc 方法来回收空间 , 该方法是由系统自动调用 , 不能手动调用验证对象 , 空间有没有没回收 , 只要查看该类的 dealloc 方法有没有执行即可,如下 - ( void )dealloc{ NSLog ( @"dealloc, 你完蛋了 , 空间回收了 " ); [ super dealloc ]; }
内存管理基本原则 : 如果你对一个对象进行 alloc retain copy 之后 ,你就 具有了该对象的所有权 , 你就必须对它进行 release 或者 autorelease. (只要调用了 alloc retain copy, 就进行 release 或
者 autorelease)
内存管理典型例子
1. 在一个对象的方法里面:假设name的语义特性为retain
self.name = [[NSString alloc] initWithFormat:@“object”];
和
_name =[[NSString alloc] initWithFormat:@“object”];
有什么不同吗?
self.name,是先给name赋值,会调用setter方法,setter方法内部进行了引用计数 + 1操作,因此它的引用计数为2
_name只是简单的赋值操作,因此引用计数不发生改变
2. - (void)setPeople:(NSString *)p{
self.people = p;
}
这段代码有什么问题。
会出现死循环,self.people会调用自己的setter,而self.people还处于setter方法内部,因此会出现死循环
3. 有一个NSStirng类型,retain方式声明的name属性的setter方法内部每一行代码的作用?
- ( void )setName:( NSString *)name {
判断原有对象和新对象是否是同一个对象 , 如果是同一个 , 就没有必要再重新赋值 , 否则会先 release 再 retain, 就会变成野指针
if ( _name != name) { 释放保有之前对象的所有权 [ _name release ]; 让实例变量 _name 保有新的对象的所有权 _name = [name retain ]; } }