Leak 內存泄漏檢測

第一次使用Leak對項目進行內存泄漏的檢測,也是查閱了許多資料,算是可以做到發現問題並解決問題。

我的項目泄漏情況是這樣的:


圖1

滿屏的紅叉讓人心慌,那麼如何找到泄露的位置呢?

首先要選中滿是紅叉的那一行,然後在這裏


圖2

選中Call Tree,

在右邊

圖3

選中Invert Call Tree 和 Hide System Libraries 兩項,Invert Call Tree 的意思是翻轉調用樹,意思就是我們在調用函數時,是一層一層的,調用外層函數會一直進入內層,直到最後一層,有點遞歸的意思,當選中 Invert Call Tree 選項時,會直接顯示內層函數,方便我們去尋找,否則會直接顯示最外層的函數,我們需要將其一層一層展開,比較費勁,不直觀。

而Hide System Libraries 的意思很明顯了。就是隱藏系統類庫,避免一些莫名其妙的,我們無法改動的信息迷惑我們。

那麼接下來我們將看到泄漏列表:


圖4

看到這裏我震驚了,強大的AFNetworking也會存在泄露?

讓我們再看看具體是哪裏除了問題,雙擊那一行我們就可以進入到具體泄漏的那個函數


圖5

可以看到每一行泄漏的byte大小都標了出來,其中藍色的爲最大。

這裏就要思考一個問題了,AFNetworking內部的這些代碼我們怎麼改呢?

不必擔心,我們發現問題出在這個方法

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

一直以來,我都以爲這是一個manager是單例,帶你進去一看其實不然,



圖6

每次調用時都會創建一個新的對象,那麼問題又來了,創建就創建唄,難道執行之後,還會不釋放?

查閱資料後果真如此,我們使用的 AFHTTPSessionManager 繼承自 AFURLSessionManager ,

創建對象時會調用傅父類的方法。


圖7

點進去看,發現其強引用一個NSURLSession對象


圖8

並且將自己設置爲了NSURLSession對象的代理


圖9

NSURLSession又是強引用代理


圖10

這樣便造成了循環引用,彼此誰也釋放不了。

那麼如何解決呢?

這裏提供兩種策略

(一)NSURLSession提供兩個方法:


圖11

這個方法會立刻取消當前任務,session對象被釋放。那麼循環引用不復存在。


圖12

而finishTasksAndInvalidate方法,則會等待任務完成時將session釋放,消除了循環引用。

我們可以在success 和 failure block中調用這兩個方法,個人推薦使用finishTasksAndInvalidate。

(二)像AFNetworking 3.0 提供的DEMO中,是這麼用的:

創建一個繼承自NSHTTPSessionManager的類,實現單例方法。


圖13

然後在自己封裝的網絡層中修改。

發佈了11 篇原創文章 · 獲贊 21 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章