ios 記憶體小結

2021-07-05 12:36:41 字數 4331 閱讀 1115

**:

這是 看 書籍  objective-c 高階程式設計 ios與os  x多執行緒和記憶體管理  一書的隨記。

除錯  

1.檢視 autoreleasepool 池裡面的物件

extern

void

_objc_autoreleasepoolprint();

_objc_autoreleasepoolprint

();

---------------上面的這個私有函式本人在ios呼叫一直沒有輸出,mac怎有。。。----------是**錯了嗎??

2.通過  clang 可以 檢視對應的 彙編**。其實xcode  的 product-》perform action ->assemble ""  也就ok了

clang -fobjc-arc -framework foundation test.m -o test  

3 通過 cfgetretaincount((__bridge    cftyperef)test2));  或者

extern

uintptr_t

_objc_rootretaincount();

nslog

(@"***x %lu"

,_objc_rootretaincount

(self

.array

));

可以在 arc 總看到 retaincount 的值。切記 不要依賴這個retaincount 編譯器 有很多優化。可能跟你理解的不同。比如 當你 通過乙個非 alloc new  copy  mutablecopy 方法獲取乙個物件的時候 按照道理是 獲取的 autorelease 物件。然後在 retain 。編譯器 會優化省略 autorelease 過程。

自己生成的物件,自己所持有

非自己生成的物件,自己也能持有

不在需要自己持有物件時釋放

非自己持有的物件 無法釋放

方法名稱 以 alloc new copy mutablecopy 開頭的方法 必須返回給呼叫者應當持有的物件。

以init 開頭的 更加嚴格 必須返回 id 型別 或者當前類的 型別 或者 子類父類。這個物件不會註冊到 autorelease 池裡面去。只是

_strong

id 型別 和物件型別 預設的修飾符。即:

id  xx = [[nsobject alloc] init]; 實際上就等於

id _strong obj = [[nsobject alloc] init ];

簡單的說 就是當 strong 修飾符修飾的變數 被賦值的時候。 就相等於 retain 了該物件。 當該修飾符 修飾的變數 拋棄原本指向的物件的時候。 就相當於 release了 該物件。當strong 修飾的變數結束了有效區域的時候。也會release

[objc]view plain

copy

mytest  *test = [[mytest

alloc

]init];  

mytest  *test2

= test;  

mytest  *test3

= test;  

mytest  *test4

= test;  

mytest  *test5

= test;  

nslog(@"retain count is %ld"

, cfgetretaincount((__bridge  

cftyperef)test));  

test5

=nil

;  nslog(@"retain count is %ld"

, cfgetretaincount((__bridge  

cftyperef)test));  

test4

= [[mytest

alloc

]init];  

nslog(@"retain count is %ld"

, cfgetretaincount((__bridge  

cftyperef)test));  

如上**所示。因為預設修飾符是strong 所以 當test 賦值給strong修飾的變數的時候。 就retain了 test。所以第乙個輸出是5. 當 執行 test5 = nil 的時候。 因為 被修飾符為 strong 的變數 拋棄的物件會release 所以 變成了4. 同樣道理 最後 test retaincount 變成了3;(ps:這裡要說的是 之前在有的資料看過 非arc 跟 arc 混編的 複雜情況下 有可能導致的記憶體洩露。 主要是 物件是非arc 建立的 在 arc中使用的情況。 當時 給出的解決方案。就是 用完之後 設定為 nil 就行了。 想想這裡的了解。其實有一定道理。當然現在找不到那個資料了所以 也沒法實驗總結)

_weak

當2個物件互相引用導致引用環的時候就需要weak了。 簡單的說就是賦值的時候 不改變 retaincount的概念。當然還有當物件釋放之後 會設定為 nil。這也是 _weak 和 __unsafe_unretain 的主要區別。

這裡有個需要注意的。當使用__weak 變數的時候。不是簡單的訪問。 是會呼叫乙個方法 retainweakreference (可以重寫這個非公開方法 用來除錯。但正式開發千萬別加邏輯。) 書上說 會加入到 autoreleasepool 裡面去。可是訪問結束檢視 autoreleasepool 。在使用訪問 __weak的時候 也確實可以檢視到 retaincount 增加了1. 這裡可以 猜測 是只是訪問的那裡新建了乙個 autoreleasepool池。訪問結束 就 已經釋放了。

這樣的作用是因為 weak 不持有該物件。當訪問過程中。可能被釋放掉。 這樣就能保證訪問過程中都是有效狀態。

_unsafe_unretained

我能想到的跟 __weak 的區別就是 釋放了物件的時候 不設定為 nil。用這個修飾符的物件 不被arc記憶體管理 所管理。

_autoreleaseing

autorelease 的本質就是 建立乙個nsautoreleasepool 物件。當乙個物件呼叫 autorelease 的時候。 會去獲取當前使用的 最內側(如果有巢狀的池的話)的nsautoreleasepool物件。然後呼叫 nsautoreleasepool物件的乙個 類似陣列 的addobject 方法。讓 nsautoreleasepool物件來持有這個 autorelease 物件。 當呼叫 nsautoreleasepool 的 drain方法的時候。清除引用。 就釋放了 autorelease物件。

實際上在arc 中 。編譯器有很多優化。讓原本是autorelease 的物件 根本就不加入到 nsautoreleasepool中去。

pd:這裡需要注意的是 指標變數 預設的修飾符 是 autoreleaseing  比如 id *xx。 是 autoreleaseing的 而 id xx 是 strong的。

屬性修飾符

assign

__unsafe_unretained

copy

__strong(是retain的複製的新物件)

retain

__strong

strong

__strong

unsafe_unretained

__unsafe_unretained

weak

__weak

這裡 感覺沒有太多的東西需要了解。 只要了解了修飾符 就會知道屬性的這些含義了。  需要注意的是 有人喜歡在類裡面的方法裡面對屬性複製的時候 用 下劃線開頭的變數。這裡不建議這樣做。 除了 初始化方法 delloc方法,以及 set get 方法內部。 其他地方 對屬性賦值的時候 盡量用屬性訪問。這是為了維護好屬性的 copy  strong 等。

另外這裡測試的時候 發現 如果在方法裡面 有個 __weak屬性  每次使用 屬性都會導致retaincount +1. 檢視彙編** 有個

_objc_retainautoreleasedreturnvalue 方法被呼叫了。完全不知道為什麼。。

看了下 _objc_autoreleasedreturnvalue 函式 返回 註冊到 autoreleasepool 裡面的物件。 但是 跟 autorelease 函式又不同。 如果 _objc_autoreleasedreturnvalue 方法之後 會立即呼叫 _objc_retainautoreleasedreturnvalue  就不將物件註冊到 autoreleasepool 中。而是直接傳遞到方法或者函式的呼叫方。 _objc_retainautoreleasedreturnvalue 和 objc_retain 函式不同。 這個作用 就是 上面說到的。 對於不是 new alloc copy mutablecopy 開頭的方法。按道理返回的物件是 autorelease 然後在retain 。這個機制就優化了這裡的**

IOS開發記憶體釋放小結

記憶體釋放是iphone開發過程中比較重的地方,所以在開闢記憶體後,我們必須小心 謹慎 並且及時的釋放掉。記憶體的釋放,可以呼叫dealloc函式,該函式可以釋放,該類物件所占用的記憶體空間,為iphone節省寶貴的記憶體資源。那麼dealloc函式是什麼時候釋放的哪?測試 如下 我們先建立乙個類 ...

iOS效能小結

最簡單的工具就是 nsdate,但精度不是太好。nsdate tmpstartdata nsdate date retain you code here.double deltatime nsdate date timeintervalsincedate tmpstartdata nslog cos...

記憶體對齊小結

原則1 結構體的資料成員,第乙個資料成員放到 0 的位置,以後每個資料成員的起始位置要從該成員大小或成員子成員大小 如陣列 的整數倍開始 原則2 結構體作為成員,如果乙個結構中有某些結構體成員,則結構體成員要從其內部最大的整數倍位址開始儲存 struct a中公有struct b,b中有char,i...