一,引用计数
属性存取方法的内存管理:
先保留新值 后释放旧值 旧值 = 新值 顺序是不能变得 如果新旧两值为同一个对象的话 那么先释放旧址 可能会导致对象内存的永久回收
autorelease:延迟对象的释放 一般在函数返回的局部变量时使用 确保对象的引用计数大于一 并且不用调用者去管理对象的释放
对象release后要赋值为nil 不管对象的内存是否真正的释放 都不要在其release后继续使用(nil就是防止继续使用 ,可能会导致程序的崩溃哦)
保留环:a->b->c->a 保留还中的对象的应用就是永远都不为0 故对象的内存不会释放 内存泄漏 解决方法是 用弱引用 打破环
二,自动引用计数(arc)
arc:编译器在代码中自动的添加内存管理函数的调用(自动执行retain release autorelease dealloc)
使用arc后手动调用retain release autorelease dealloc会报错 因为你已经将内存管理交给编译器了 你就不能插手去干扰它工作
使用arc在编译器间会进行一些编译器的优化 抵消retain 和 release
变量的内存语义:每个变量都是指向对象的强引用
改变变量内存语义的修饰符:
__strong :保留 __unsafe_unretained:不保留 __weak:不保留 自动赋值nil __autoreleasing:引用传递时 调用完函数会自动释放
三,dealloc 方法内释放引用和解除监听
dealloc应由系统调用不应该自己调用 应该系统处理这个函数的时机并不确定
dealloc应该释放oc对象和c对象(使用arc的话系统则会自动释放)
不要再dealloc中释放大块的资源 因为dealloc被系统调用的时机是不确定的 这样可能资源被持有的时机过长 故应该主动的调用函数释放
不要再dealloc中调用其它方法 因为对象已经在生命末期 如果有异步情况下 要回调 但对象已经消亡了 会出现崩溃
不要在dealloc中使用属性存取方法 有人可能复写这些方法 做一些回收阶段不安全的操作 (不在dealloc中调用任何方法就好了)
四,异常安全代码的内存管理问题
oc与c++的异常时相互兼容的 可以交叉使用
arc不会生成异常安全的代码 修改编译器选项后 可生成清理代码 但是会导致程序效率变低
在oc中不要抛出异常除非是一些会令程序终止的错误 因为抛出了异常很容易导致内存泄漏 程序终止后会回收资源 故内存泄漏了也不会导致很严重的问题
写循环时要注意临时对象都会加入自动释放池 导致程序的内存升高 可以通过每次循环都进行一次释放解决这个问题
可以修改编译选项 打开僵尸对象 僵尸对象就是对象释放后他的那块内存 不会分配给他人使用(其实就是在dealloc中不释放内存,只是修改类的isa指针) 这样有助于调试
在实际发行时 并不会打开这个选项(因为这个选项会导致内存泄漏)
僵尸对象可以相应所有函数(函数只是答应调试信息 并终止进程)
五,不要使用reCount
不要使用reCount控制对象的生命周期 因为reCount返回的数值是一个不准确的值
1. 他也不会考虑延迟释放问题 如果把一个对象recount是1 再把他加入到自动释放池中 recount返回的还是一 如果用它做判断将对象释放掉 那么在自动释放池中释放会导致崩溃
2.系统可能进行优化 当对象的引用计数为1的时候就将其释放掉 那么recount的返回值就永远不为0
3.系统可能基于某种用途 把他设置为一个很大的值 为了不让这个对象释放掉