iOS面試題:常見的內存泄漏有哪些狀況?如何排查和避免?

面試題:常見的內存泄漏有哪些狀況?如何排查和避免?web

內存泄漏原理:在百度上的解釋就是「程序中已動態分配的堆內存因爲某種緣由程序未釋放或沒法釋放,形成系統內存的浪費,致使程序運行速度減慢甚至系統崩潰等嚴重後果」。面試

  • 常見的內存泄漏狀況:

    • 狀況一:對象之間的循環引用問題 循環引用的實質:多個對象相互之間有強引用,不能施放讓系統回收。解決辦法:使用 weak 打破對象之間的相互強引用app

    • 狀況二: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)也就是編譯,主要分析如下四種問題:atom

    • 邏輯錯誤:訪問空指針或未初始化的變量等;
    • 內存管理錯誤:如內存泄漏等;
    • 聲明錯誤:從未使用過的變量;
    • Api調用錯誤:未包含使用的庫和框架。
  • 第二種查詢方式Instruments中的Leak動態分析內存泄漏,product->profile ->leaks 打開工具主窗口代理

  • 第三種Facebook早已開源了一款檢測內存問題的三方庫FBRetainCycleDetector指針


更多:iOS面試題 答案合集 更多:《BAT面試答案文集.PDF》,獲取可加iOS技術交流圈:937194184,相互交流。code

相關文章
相關標籤/搜索