ARC下的内存泄漏

iOS的内存管理一般指oc对象的内存管理,oc对象一般保存在堆内存里面;非oc对象保存在栈内存里面,超出作用域系统就会自动回收。

从MRC到ARC做了什么?

每个对象都有相对应的引用计数器,当一个对象被引用或者被持有的时候,引用计数就会加1;当改对象的某个持有被释放时,引用计数就会减一。当该对象的引用计数为0的时候,该对象就会被释放。
引用计数的存储形式:散列表

struct SideTable {
    spinlock_t slock;
    RefcountMap refcnts;
    weak_table_t weak_table;

    SideTable() {
        memset(&weak_table, 0, sizeof(weak_table));
    }

    ~SideTable() {
        _objc_fatal("Do not delete SideTable.");
    }

    void lock() { slock.lock(); }
    void unlock() { slock.unlock(); }
    void forceReset() { slock.forceReset(); }

    // Address-ordered lock discipline for a pair of side tables.

    template
    static void lockTwo(SideTable *lock1, SideTable *lock2);
    template
    static void unlockTwo(SideTable *lock1, SideTable *lock2);
};
// RefcountMap disguises its pointers because we 
// don't want the table to act as a root for `leaks`.
typedef objc::DenseMap,size_t,true> RefcountMap;
// Template parameters.
enum HaveOld { DontHaveOld = false, DoHaveOld = true };
enum HaveNew { DontHaveNew = false, DoHaveNew = true };

从上面的C++源码可以看出,引用计数保存在散列表里,其结构体有弱引用表。散列表会设置新值和旧值,引用计数的变化。
但是实际上引用计数的存储不止保存在散列表里面,还有一些其他的情况,这里做了一下总结:
1.对象支持使用 TaggedPointer,将对象的指针值作为引用计数返回。
2.不支持TaggedPointer:

  • 64位环境并且使用 Objective-C 2.0,会用isa指针部分空间 (bits.extra_rc)存储引用计数;
  • 最终选择Runtime会使用一张散列表(SideTables)来管理引用计数。

此外,还增加了strong和weak主要关键字,来取代retain和assign,废弃了__unsafe_unretain,代码使用起来更加的方便。
weak的管理保存在一张hash表中,具体原理:
(1) 从weak表中获取废弃对象的地址为键值的记录;
(2) 将weak表中的所有__weak修饰变量的地址,赋值为 nil;
(3) 从 weak 表中删除该记录;
(4) 从引用技术表中删除废弃对象的地址为键值的记录。

ARC下的内存泄漏

  1. 由于strong属性导致的block循环引用;
  2. NSTimer引起的循环应用;
  3. 通知中心不释放观察者引起的内存泄漏
  4. 坏内存访问
  5. 方法没有找到对应的消息源

你可能感兴趣的:(ARC下的内存泄漏)