知识点总结

iOS 内存布局&内存管理

2019-04-15  本文已影响5人  飞不越疯人院

1. 内存布局


2. 内存管理

系统堆内存的管理不同的场景有不同的管理方案;

里面是SideTables结构; SideTable(哈希表)包含spinlock_t(自旋锁), RefcountMap(引用计数表), weak_table_t(弱引用表)几部分;

自旋锁:是一个忙等的锁(当锁被占用时会不停的检测当前线程去尝试使用, 不会阻塞线程); 适用于轻量级的访问;
引用计数表:通过hash表实现;原因是为了提高查找效率(因为插入和查找是通过同一个hash算法进行的, 避免循环遍历);
弱引用表:通过hash表实现;原因是为了提高查找效率(因为插入和查找是通过同一个hash算法进行的, 避免循环遍历);


3. MRC和ARC

关键词含义:

知识点:系统是如何将weak变量添加到弱引用表中的?
被声明成__weak的对象指针在通过编译后会依次调用objc_initWeak(), storeWeak(), weak_register_no_lock()几个函数;最终在weak_register_no_lock()函数中进行弱引用变量的添加, 添加的位置时通过hash算法进行位置查找的, 如果查找到相应位置已经有了当前对象所对应的弱引用变量数组就把新的弱引用变量添加到数组, 如果没有则重新创建弱引用数组并在第0个位置添加最新的weak指针(数组有四个元素:其余的初始化为nil);

知识点:当weak修饰的变量在dealloc时置为nil的过程?
对象被dealloc后, 在dealloc内部实现中经过一系列的调用最终在weak_clear_no_lock()函数中根据当前对象指针查找弱引用表,把当前对象相对应的(数组)弱引用取出遍历置为nil;


4. 自动释放池

什么是自动释放池?
  1. 自动释放池是OC提供的一种回收机制,具有延迟释放的特性
  2. 为节点通过双向链表形式组合而成;
    (每一个自动释放池没有单独结构, 它是有若干个autoreleasePoolPage通过双向链表链接而成)
  3. 与线程一一对应(看autoreleasePoolPage的结构);

使用场景? 例:在for循环中alloc图片数据等内存消耗较大的场景时手动插入@autoreleasePool; 每次for循环结束进行一次内存释放, 防止内存峰值过大;

编译器会将@autoreleasepool()改写为以下代码
void *ctx = objc_autoreleasePoolPush();
{相关代码}
objc_autoreleasePoolPop(ctx);

AutoreleasePoolPage结构:

class AutoreleasePoolPage {
    magic_t const magic;
    id *next;//指向栈顶最新被添加进来的autorelease对象的下一个位置
    pthread_t const thread;//指向当前线程
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;
    uint32_t 
  }
magic用来校验AutoreleasePoolPage结构是否完整;
next指向第一个可用的地址;
thread指向当前的线程;
parent双向链表中指向父指针;
child双向链表中指向子指针;

上一篇下一篇

猜你喜欢

热点阅读