iOS 面试

iOS autoreleasepool 原理

2019-12-15  本文已影响0人  孙掌门

iOS autoreleasepool 原理

 NSMutableArray *arr = [NSMutableArray array];
 NSLog(@"%@",arr);

arr 是再什么时机释放?

@AutoreleasePool{代码} 会被编译器改写为

void *ctx = objc_autoreleasePoolPush();

{}代码

objc_audoreleasePoolPop(ctx);

源码

objc_autoreleasePoolPush(void)
{
    return AutoreleasePoolPage::push();
}

void
objc_autoreleasePoolPop(void *ctxt)
{
    AutoreleasePoolPage::pop(ctxt);
}

一次 pop 相当于一次批量的pop操作

AutoreleasePool 实现原理

是以栈为节点通过双向链表的形式组合而成的,是和线程一一对应的

autoreleasePoolPage 数据结构

可在源码中查看


    id *next;
    pthread_t const thread;
    AutoreleasePoolPage * const parent;
    AutoreleasePoolPage *child;
    uint32_t const depth;

next 其实就是指向栈中下一个可填充的位置,parent 和 child 也就是双向链表的父指针和子指针,

栈顶 --- 低地址

next

id obj

id obj --- 栈底

AutoreleasePoolPage --- 高地址,自身占用内存

所以发生push,会把当前哨兵next位置指向nil,指向下一个位置,其实就是在栈中插入对象

[obj autorelease]过程

首先会判断是否到达了栈顶,没有的话就添加到栈中,增加一个栈节点到链表上面

pop 过程

1.根据传入的哨兵对象找到对应的位置

2.给上次push操作之后添加的对象一次发送release消息

3.会退到next指针的位置

所以上面的题,是再档次runloop将要结束的时候调用 autoreleasePoolPage::pop(),然后发送release消息,也就是pod操作,从栈中移除

AutoreleasePool 为何可以嵌套使用

多层嵌套就是多次插入哨兵对象,每次创建一个AutoreleasePool,@AutoreleasePool,其实系统就是为我们创建了一个哨兵对象,其实就是创建page,若果当前page没有满,其实就是创建一个哨兵,所以可以嵌套使用

一般什么时候用

比如for循环alloc图片等内存消耗比较大的数据,需要插入,防止当时内存消耗过大

上一篇下一篇

猜你喜欢

热点阅读