iOS與記憶體管理

2021-07-09 03:11:04 字數 1625 閱讀 3404

記憶體工具

針對ios開發,我們所能使用的記憶體排查工具選擇其實並不算特別多。最主要的除錯工具就是instruments。然而,如果仔細探查細節,instruments還是整合了很多不錯的除錯模板/library的。

本文針對如下幾類應用場景,對通用的除錯方法做基本介紹:

1. 記憶體洩露與過度釋放

我們應該都知道,ios開發過程中,使用objective-c分配的堆記憶體都是通過引用計數來做保留和釋放的。一塊記憶體初始分配,引用計數為1,此後每新增乙個強引用,引用計數增加1;釋放正好相反,每一次release,引用計數減1,直到為0,物件所用記憶體被真正free掉,以被再次復用。然而,實際開發當中,總有一些原因導致引用計數無法按正常邏輯減少到0,或者減少到0之後仍然被呼叫release,前者是記憶體洩露,後者則是過度釋放。

當執行時發生顯示記憶體洩露時,leaks會在時間軸上標出紅色指示線,同時在instruments的下方會列出呼叫細節,結合系統提供的malloc歷史,其中包含引用計數變化情況,以及呼叫棧可以很直接地找到洩露原因。

同時對於一些「隱式」的情況,需要反覆操作,同時觀察allocation中只增不減,一直建立新物件而不釋放老物件的情況。

過度釋放,是對同乙個物件釋放了過多的次數,其實當引用計數降到0時,物件占用的記憶體已經被釋放掉,此時指向原物件的指標就成了「懸垂指標」,如若再對其進行任何方法的呼叫,(原則上)都會直接crash(然而由於某些特殊的情況,不會馬上crash)。

對於這種問題,可以直接使用zombie,當過度釋放發生時會立即停在發生問題的位置,同時結合記憶體分配釋放歷史和呼叫棧,可以發現問題。

至於上文提到的不會crash的原因,其實有很多,比如:

2. malloc庫提供的相關工具

scribble其實是malloc庫(libsystem_malloc.dylib)自身提供的除錯方案,除了scribble,malloc還提供了很多其它的除錯工具/方案,在diagnostics tab下你應該都看到了。其實,malloc可用的工具還不止這些,通過環境變數至少還可以新增如下除錯引數:

其中,有幾個引數是和記錄分配歷史的日誌有關的。

除此之外,xcode裡還提供了guard malloc,這個是等同於預設malloc庫功能的另外乙個除錯庫,為了定位大記憶體越界訪問問題,不過只能在模擬器上使用(個人分析是因為真機根本承受不起保護頁記憶體消耗)。

對以上引數的實現細節感興趣的,可以參看蘋果開放出來的malloc原始碼。

3. 其它

下面我還想對instruments裡的三樣東西做簡要介紹:

allocation針對堆記憶體及匿名對映的情況提供了詳細的資料,包括某類物件有多少個,物件的具體位址,占用多大記憶體等。通過allocation,可以對我們開發中實際接觸到的記憶體有非常全面的把握。

vm tracker則可以告訴我們哪些部分是dirty的,dirty的資料系統不會直接清理掉,因為這些資料是被寫過的,無法通過外部儲存直接生成,只能維持在記憶體當中。此外,通過vm tracker我們還可以看到region map,看到程序位址空間各部分的對映情況。

除了上面提到的這些,對於詭異的記憶體問題,我們可以對xcode7中的address sanitizer期待和試用下,也許它真得能幫我們解決好多問題!

ios記憶體管理

引用計數 每個物件有乙個與之相關的整數,稱作 引用計數器 或者 保留計數器 當某段 需要訪問乙個物件時,該段 會將物件的保留計數器 1,表示需要訪問這個物件 當結束對該物件的訪問時,保留計數器 1,表示它不在訪問該物件 當保留計數器為0時,物件被銷毀,所佔記憶體被系統收回。當使用new retain...

iOS記憶體管理

前提 1 以下是針對cocoa物件,不包括core foundation 2 cocoa物件都是用引用計數來跟蹤物件的記憶體使用情況的。3 在子類裡面父類先初始化和後釋放的原則。自己想下為什麼 棧空間和堆空間的區別。我們說的記憶體管理都是基於堆空間的,因為函式內的棧空間是由編譯器自己控制的。關於co...

IOS 記憶體管理

範圍 任何繼承了nsobject的物件,對基本資料型別無效 原理 每個物件內部都儲存了乙個與之相關聯的整數,稱為引用計數器 當使用alloc new或者copy建立乙個物件時,物件的引用計數器被設定為1 給物件傳送一條retain訊息,可以使引用計數器值 1 給物件傳送一條release訊息,可以使...