AutoreleasePool原始碼分析

2021-09-05 10:32:39 字數 2924 閱讀 3869

現在我們已經進入了arc時代,編譯器幫我們在編譯**時自動對變數進行記憶體管理,使開發者不用再為了物件因為記憶體管理問題而頭疼。autoreleasepool是自動釋放池,當我們在使用@autoreleasepool塊時,自動釋放池將會對池內物件進行管理,直到變數不被使用時,將其記憶體進行**。

struct __atautoreleasepool 

~__atautoreleasepool()

void * atautoreleasepoolobj;

};__atautoreleasepool __autoreleasepool;

分析:當使用clang編譯後我們可以看到生成了runtime原始碼,__atautoreleasepool是乙個結構體,包含了乙個objc_autoreleasepoolpush操作和乙個析構函式,函式裡呼叫的是objc_autoreleasepoolpop操作。

static inline void *push() 

autoreleasefast實現

static inline id *autoreleasefast(id obj)

else if (page) else

}

autoreleasepool沒有單獨的記憶體結構,而是以autoreleasepoolpage為結點的雙向鍊錶將物件進行存放,通過nsobject.mm原始碼我們知道:

每乙個autoreleasepoolpage類的定義如下:

class autoreleasepoolpage 

magin:檢測autoreleasepoolpage結構的完整性;

thread:指向當前執行緒;

depth:代表深度,從 0 開始,往後遞增 1;

hiwat:代表 high water mark ;

push原理分析:

static inline void pop(void *token) 

else if (debugmissingpools && page->empty() && !page->parent)

}}遍歷將所有遍歷kill掉

void kill()

delete deathptr;

} while (deathptr != this);

}

原理分析:

__weak nsstring* weakstring = nil;

nslog(@"%@", weakstring);

}

nslog(@"%@", weakstring);

}- (void)viewdidload

nslog(@"%@", weakstring);

// 情景3

@autoreleasepool

nslog(@"%@", weakstring);

// 情景4

nsstring* string = nil;

@autoreleasepool

nslog(@"%@", weakstring);

// 情景5

@autoreleasepool

nslog(@"%@--%lu", weakstring, [weakstring retaincount]);

}

結果:

情景一:

autorelease[43423:1093743]helloworld

autorelease[43423:1093743]helloworld

autorelease[43423:1093743](null)

情景二:

autorelease[43423:1093743]helloworld

autorelease[43423:1093743]helloworld

autorelease[43423:1093743]helloworld

情景三:

autorelease[43423:1093743](null)

autorelease[43423:1093743](null)

autorelease[43423:1093743](null)

情景四:

autorelease[43423:1093743]helloworld

autorelease[43423:1093743]helloworld

autorelease[43423:1093743]helloworld

情景五:

autorelease[43423:1093743]mjz--18446744073709551615

autorelease[43423:1093743]mjz

autorelease[43423:1093743]mjz

呼叫類的init方法生成物件引用計數為1,此時用string指向此物件後,string物件的引用計數為2,當autoreleasepool銷毀後,string物件被系統**,此時對應引用計數為1,再列印weakstring的值仍然存在;

呼叫類的類方法生成string物件引用計數為1,所以當autoreleasepool銷毀後,string物件引用計數變0,記憶體也被**,所以weakstring為nil;

這種情況與情景2類似,string物件引用計數為2,當autoreleasepool銷毀後,string物件變為1,所以此時weakstring指向的字串仍然存在;

string物件是常量字串,存放在棧區,所以不存在引用計數,只有存放堆區的物件才存在引用計數。

此處列印?與網上的資料稍有偏差,以上是我實踐的結果!!!

自動釋放池 Autorelease Pools

自動釋放池 autorelease pools 每個執行緒都維護它自己的 nsautoreleasepool 的棧物件。cocoa 希望在每個當前 執行緒的棧裡面有乙個可用的自動釋放池。如果乙個自動釋放池不可用,物件將不會給釋放,從而造成記憶體洩露。對於 的主線程通常它會自動建立並消耗乙個自動釋放池...

自動釋放池autoreleasepool

物件存入到自動釋放池中,當這個池子被銷毀的時候,他都會對池子中的所有的物件進行一次release操作 1 怎麼把物件存到池子中 自動釋放池,大括號代表池子的作用域,可以自己隨意建立 只有在自動釋放池的作用域中呼叫物件的autorelease方法才能夠正確地將物件放入到池子中 autoreleasep...

關於 autoreleasepool的測試及使用

void dosomething nslog finished void dosomething nslog finished 綜上,當需要在程式中建立大量的臨時變數時 大量也可指數量多,不確定,比如從資料庫中讀取資料時 很容易使記憶體產生峰值又回到記憶體低谷,這樣對程式的效能會產生很大影響,而使用...