美文网首页iOS面试题合集(上)
iOS面试题:常见的内存泄漏有哪些情况?如何排查和避免?

iOS面试题:常见的内存泄漏有哪些情况?如何排查和避免?

作者: iOS猿_员 | 来源:发表于2020-08-08 15:13 被阅读0次

    面试题:常见的内存泄漏有哪些情况?如何排查和避免?

    内存泄漏原理:在百度上的解释就是“程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果”。

    • 常见的内存泄漏情况:

      • 情况一:对象之间的循环引用问题
        循环引用的实质:多个对象相互之间有强引用,不能施放让系统回收。解决办法:使用 weak 打破对象之间的相互强引用

      • 情况二:block的循环引用
        blockcopy时都会对block内部用到的对象进行强引用的。解决办法使用:使用__weak打破循环的方法只在 ARC下才有效,在 MRC 下应该使用__block

      __weak typeof(self) weakSelf = self; self.myBlock = ^() { // 除了下面的还有 调用 self的一些属性等等 [weakSelf doSomething] };
    
    • 情况三: delegate 的循环引用
      delegate是委托模式.委托模式是将一件属于委托者做的事情,交给另外一个被委托者来处理,在这里我们可能会出现委托者和被委托人之间的相互强引用问题;解决办法:在声明 delegate 属性的时候 用weak 进行弱引用 或者 通过中间对象(代理对象)的方式来解决(效率更加高的中间对象NSProxy:不需要进行发送消息和再动态解析,直接进行消息转发)
    @property(nonatomic, weak) id delegate;
    
    • 情况四CADisplayLinkNSTimer会对target产生强引用,如果target又对它们产生强引用,那么就会引发循环引用;解决办法:NSTimer 有一个block的方法,我们可以利用block的弱指针来解决__weak typeof(self) weakSelf = self;weakSelf 进去

    • 情况五:通知的循环引用
      iOS9 以后,一般的通知,都不再需要手动移除观察者,系统会自动在dealloc 的时候调用 [[NSNotificationCenter defaultCenter] removeObserver: self]iOS9 以前的需要手动进行移除。原因是:iOS9 以前观察者注册时,通知中心并不会对观察者对象做 retain 操作,而是进行了 unsafe_unretained 引用,所以在观察者被回收的时候,如果不对通知进行手动移除,那么指针指向被回收的内存区域就会成为野指针,这时再发送通知,便会造成程序崩溃。从 iOS9 开始通知中心会对观察者进行 weak 弱引用,这时即使不对通知进行手动移除,指针也会在观察者被回收后自动置空,这时再发送通知,向空指针发送消息是不会有问题的。建议最好加上移除通知的操作:

    (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self.observer name:@"name" object:nil]; }
    
    • 情况六:WKWebView 造成的内存泄漏
      总的来说,WKWebView 不管是性能还是功能,都要比 UIWebView 强大很多,本身也不存在内存泄漏问题,但是,如果开发者使用不当,还是会造成内存泄漏。请看下面这段代码:
    @property (nonatomic, strong) WKWebView *wkWebView;
    
    *   (void)webviewMemoryLeak { WKWebViewConfiguration *config =[[WKWebViewConfiguration alloc] init]; 
    config.userContentController = [[WKUserContentController alloc] init]; 
    [config.userContentController addScriptMessageHandler:self name:@"WKWebViewHandler"]; 
    _wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; 
    _wkWebView.backgroundColor = [UIColor whiteColor]; 
    [self.view addSubview:_wkWebView];
     NSURLRequest *requset = [NSURLRequest requestWithURL:[NSURL URLWithString:@"[https://www.baidu.com](https://www.baidu.com/)"]];
     [_wkWebView loadRequest:requset]; } 这样看起来没有问题,但是其实 “addScriptMessageHandler” 这个操作,导致了 wkWebView 对 self 进行了强引用,然后 “addSubview”这个操作,也让 self 对 wkWebView 进行了强引用,这就造成了循环引用。解决方法就是在合适的机会里对 “MessageHandler” 进行移除操作:
    
    *   (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; 
    [_wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"WKWebViewHandler"]; }
    
    
    • 内存泄漏的查询

    • 第一种查询方式Analyze 静态分析 (command + shift + b)也就是编译,主要分析以下四种问题:

      • 逻辑错误:访问空指针或未初始化的变量等;
      • 内存管理错误:如内存泄漏等;
      • 声明错误:从未使用过的变量;
      • Api调用错误:未包含使用的库和框架。
    • 第二种查询方式Instruments中的Leak动态分析内存泄漏,product->profile ->leaks 打开工具主窗口

    • 第三种Facebook早已开源了一款检测内存问题的三方库FBRetainCycleDetector


    更多:iOS面试题 答案合集
    更多:《BAT面试答案文集.PDF》,获取可加iOS技术交流圈:937194184,相互交流。

    相关文章

      网友评论

        本文标题:iOS面试题:常见的内存泄漏有哪些情况?如何排查和避免?

        本文链接:https://www.haomeiwen.com/subject/kddhdktx.html