内存管理面试问题

1.0 内存管理相关

问题1: retain实现?

retain的时候系统是怎样查找对应的引用计数的?

        经过两次哈希查找查找到它的引用计数值进行相应的+1操作

问题2:release实现?

问题3:delloc的实现?

     

 总结:首先调用_objc_rootDealloc()私有函数,这个函数会调用rootDealloc()函数,然后在这个函数内部当前对象是否可以直接释放,是否可以直接释放的判断条件如下:

        1:nonpointer_isa 当前对象是否使用了非指针型的isa

        2:weakly_referenced 当前对象是否有weak指针指向weakly_referenced

        3:has_assoc 当前对象是否有关联对象

        4:has_css_dtor 当前对象的内部实现是否有涉及到一些c++相关内容以及当前对象是否使用ARC来管理,如果说当前对象涉及到了c++相关内容或者ARC管理内存这个判断标志就是YES

        5:has_sidetable_rc 当前对象的引用计数是否是在通过sideTable中当的引用计数表来维护的。

        结论:只有当前对象既不是非指针型isa的指针,同时没有弱引用,并且也没有关联对象,也没有涉及到c++的相关内容并且没有涉及到ARC,并且没有采用sidetable来存储相关引用计数,只有在这种条件下才可以调用c函数直接释放,否则就要调用object_dispose()对象清除的一个函数。

        如果当前对象这些条件都不满足的情况下,那么可以直接调用c函数的free()来进行对象的内存释放,否则就要在调用一个函数做一个后续的清理。

                

 

问题4:循环引用

        自循环引用

        相互循环引用 

        多循环引用

问题4.1:如何破除循环引用?

        避免产生循环引用        

        在合适的时机手动断环

问题4.2:具体的解决方案有哪些?

__weak        

__block

        MRC下, __block修饰对象不会增加其引用计数,避免了循环引用

        ARC下, __block修饰对象会被强引用,无法避免循环引用,需要手动解环

__unsafe_unretained

        修饰对象不会增加其引用计数,避免了循环引用。

        如果被修饰对象在某一时机被释放,会产生垂悬指针

问题4.3:循环引用的示例?

        NSTimer的循环引用问题?


面试总结

问题1:什么是ARC ?

        ARC是由LLVM编译器RunTime共同协作来为我们实现自动引用计数的管理。

问题2:为什么weak指针指向的对象在废弃之后会被自动置为nil ?

        在对象被废弃之后delloc方法的内部实现当中会调用清除弱引用的一个方法,在清除弱引用的方法中会通过哈希算法来查找被废弃对象在弱引用表中的位置来提取它所对应弱引用指针的列表数组进行for循环遍历把每一个weak指针都置为nil。

问题3:苹果是如何实现AutoreleasePool的?

        AutoreleasePool是以栈为节点,由双向链表形式来合成的数据结构。

问题4: 你遇到过哪些循环引用,是怎么解决的?

        NSTimer循环引用,对NSTimer创建一个分类文件添加一个分派定时器的方法,参数与系统方法一致,定义中间对象,定义一个weak弱引用的target,一个assign的selector定时器到时后的回调方法一个weak弱引用的NSTimer,定义一个中间对象的执行方法对target进行判断,如果当前target仍然存在的话那么判断它是否响应这个选择器,如果响应就执行对应的回调方法,否则就调用invalidate置为无效,这样就能可以达到RunLoop对timer强引用的释放,同时timer也会释放对弱引用对象的释放。在分类方法中target和selector分别指派给中间对象,在用系统方法去创建NSTimer同时指定timer的回调是中间对象的执行方法,在中间对象的执行方法中在对实际对象回调方法进行调用。

@interface TimerWeakObject : NSObject
@property (nonatomic, weak) id target;
@property (nonatomic, assign) SEL selector;
@property (nonatomic, weak) NSTimer *timer;

- (void)fire:(NSTimer *)timer;
@end

@implementation TimerWeakObject

- (void)fire:(NSTimer *)timer
{
    if (self.target) {
        if ([self.target respondsToSelector:self.selector]) {
            [self.target performSelector:self.selector withObject:timer.userInfo];
        }
    }
    else{
        [self.timer invalidate];
    }
}

@end

@implementation NSTimer (WeakTimer)

+ (NSTimer *)scheduledWeakTimerWithTimeInterval:(NSTimeInterval)interval
                                         target:(id)aTarget
                                       selector:(SEL)aSelector
                                       userInfo:(id)userInfo
                                        repeats:(BOOL)repeats
{
    TimerWeakObject *object = [[TimerWeakObject alloc] init];
    object.target = aTarget;
    object.selector = aSelector;
    object.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:object selector:@selector(fire:) userInfo:userInfo repeats:repeats];
    
    return object.timer;
}

问题5:NStimer准吗?谈谈你的看法?如果不准该怎样实现一个精确的NSTimer?  实际上面试官是在看你懂不懂Runloop

1.无论是单次执行的NSTimer还是重复执行的NSTimer都不是准时的

2这与当前NSTimer所处的线程有很大的关系,如果NSTimer当前所处的线程正在进行大数据处理(假设为一个大循环),NSTimer本次执行会等到这个大数据处理完毕之后才会继续执行。这期间有可能会错过很多次NSTimer的循环周期,但是NSTimer并不会将前面错过的执行次数在后面都执行一遍,而是继续执行后面的循环,也就是在一个循环周期内只会执行一次循环。

所以我们要习惯把NSTimer放在Runloop中去执行,       [NSRunLoop currentRunLoop];//获取当前线程的Runloop      [NSRunLoop mainRunLoop];//获取主线程的Runloop


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值