1. 程式人生 > >關於對iOS中自動釋放池autoreleasepool的一些理解

關於對iOS中自動釋放池autoreleasepool的一些理解

因為現在大家都在使用ARC模式下進行程式設計,一個很重要的問題也是最容易被大家所忽視的問題就是自動釋放池,大部分程式設計師尤其是剛入行的都只是知道有這麼一個東西,但具體是什麼,工作的原理是什麼,在什麼時候使用它都一概不知。所以寫一篇文章,記錄一下個人對自動釋放池的一些理解。

我們新建一個OC專案,在main函式中可以看到這麼一串程式碼:

int main(int argc, char * argv[]) {     @autoreleasepool {         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));     } }

其中就引用了一個自動釋放池。其實,自動釋放池@autoreleasepool{}在系統中所編譯的程式碼為:

1.void *ctx = objc_autoreleasepoolPush();     //建立一個無型別指標的哨兵物件

2.執行@autoreleasepool{}中對應{}裡所書寫的程式碼

3.執行objc_autoreleasepool(ctx);//釋放哨兵物件所分隔區域內所有物件的引用計數

由以上可以看出,autoreleasepool工作的原理就是一個壓棧,一個出棧,push方法建立哨兵物件作為標記,pop操作作批量引用計數釋放的工作。

介紹完大概程式碼的原理之後說一下一個比較官方的對於autoreleasePool的總結吧。

autoreleasepool是以棧為節點,通過雙向連結串列的形式組合而成的,autoreleasepool是與執行緒一一對應的。

那麼什麼是雙向連結串列呢,雙向連結串列的單位是節點,從頭結點開始一直到尾節點,每一個節點都會有一個父指標和子指標,父指標指向前一個節點,子指標指向後一個節點,而頭節點的父指標指向NULL,尾節點的子指標指向NULL。這樣就把棧空間通過雙向連結串列的形式連線起來了。

而autoreleasepoolPage就是雙鏈連結串列中每一個節點的長度了,可以說,autoreleasepoolPage把棧空間中一些大小的空間分割成一個個單位,稱為節點,然後通過雙向連結串列的形式連線起來,這就成了一個整體的autoreleasepool的結構了。

在AutoreleasePool中有四個變數分別是:1.id *next一個id型別的指標,指向的是下一個可儲存物件的位置,2.AutoreleasepoolPage* const parent;這就是當前page父節點page的地址指標。3.AutoreleasepoolPage* child,同理,是子節點表地址的指標。4.pthread_t const thread;這個變數中就記錄了執行緒的情況,所以說自動釋放池是與執行緒一一對應的關係。

在介紹了自動釋放池整體結構之後,接下來就說自動釋放池關大象的三個步驟:

一、把冰箱門開啟

呼叫objc_autoreleasepoolPush()方法,在當前autoreleasepoolPage中的next指標位置建立一個為nil的哨兵物件,隨後將next指標的位置指向下一個記憶體地址。

二、把大象關進去

第二步就是執行程式碼了,在自動釋放池範圍內的程式碼被執行,給逐個物件呼叫[object autorelease]方法。其實在autorelease方法內部實現的步驟為:1.判斷next指標是否已經在棧頂了,如果是,則增加一個棧節點到連結串列上,隨後增加一個物件到新的棧節點連結串列中,如果不是的話則在next指標所指的位置新增一個呼叫autorelease方法的物件。

三、把冰箱門關上(其實是把大象取出來)

第三部就是執行objc_autoreleasepoolPop()方法,該方法會根據傳入的哨兵物件找到對應的記憶體位置,然後根據哨兵物件的位置給上次push後新增的物件依次傳送release訊息,然後回退next指標到正確的位置。

以上三個步驟就是在autorelease自動釋放池中進行的操作,也是這三個步驟構成了自動釋放池。

所以總結一下,main函式中的autoreleasepool是在runloop結束的時候呼叫objc_autoreleasepoolPop的方法的,多層巢狀的autoreleasepool其實就是在棧中多次插入哨兵物件,而在我們開發的過程中,通過for迴圈載入一些佔用記憶體較大的物件時可以巢狀使用autoreleasepool,在這些物件使用完畢的時候及時被釋放掉,這樣就不會造成記憶體過大或過多浪費的情況啦~

本文章由作者原創,未經允許不得轉載!