將block賦值給strong 型別的block變數,或者賦值給strong 修飾的物件型別中的block成員變數時,block會從棧複製到堆上。那__block變數會有什麼變化呢?
其實,當block 被從棧複製到堆上時,block中使用到的變數也會從棧賦值到堆上。
當block被從棧複製到堆前後,__block變數儲存域變化如下:
而如果配置在堆上的block被廢棄,那麼它所使用的__block變數也會被釋放。
從這裡可以看出__block變數的管理,與objective-c的引用計數記憶體管理方式很相似。使用__block變數的block,持有__block變數。如果block被廢棄,它所持有的__block變數也會被釋放。
這裡回顧一下,__block變數內部的__forwarding成員變數作用?
因為__block變數從棧複製到堆,所以在某乙個時刻會有兩個__block變數,如果將棧上的__forwarding指向堆上的__block變數,就可以保證不管你訪問的是棧上的__block變數,還是堆上的__block變數,實際上訪問的都是堆上的__block變數。
這樣,寫法是一致的,而且不管棧上的__block變數是否被釋放,都能通過變數的指標位址正確的訪問到堆上的__block變數。這樣的設計真是非常完美。
當block 中使用__block變數時,__main_block_desc_0
結構體內部會多出兩個成員變數copy
和dispose
,這兩個成員變數是函式指標型別,裡面分別儲存著兩個靜態函式__main_block_copy_0
和__main_block_dispose_0
。
enum
;
__main_block_copy_0
函式是將block內使用的__block變數,賦值給目標block用結構體成員變數中,如果是物件型別變數,則持有它。
static
void
__main_block_copy_0
(struct __main_block_impl_0*dst,
struct __main_block_impl_0*src)
_block_object_assign
函式當複製的是物件型別變數時,相當於retain例項方法,將物件型別變數賦值在__main_byref_name_1這樣的結構體變數的成員變數中。
__main_block_dispose_0
函式內部使用_block_object_dispose
函式,來釋放賦值在block結構體中的成員變數。
static
void
__main_block_dispose_0
(struct __main_block_impl_0*src)
_block_object_dispose
函式中如果傳的是物件,則相當於release例項方法的函式,如果是非物件,猜測就是普通的釋放變數了。
在clang 轉換出來的c++**中沒有看到呼叫__main_block_copy_0
和__main_block_dispose_0
的地方,據說是在執行時將block從棧複製到堆時以及堆上的block被廢棄時會呼叫這些函式。(這個目前還無法確認)
呼叫copy函式和dispose函式的時機
函式呼叫時機
copy函式
棧上的block複製到堆時
dispose函式
堆上的block被釋放時
在哪些場景下棧上的block會複製到堆上呢?
在這些場景下,block就會被從棧上覆制到堆上。
為什麼在物件中新增block型別的property時,要使用copy修飾符?
其實在arc下,使用strong
,retain
和使用copy
是一樣。
我們都知道,在arc下,使用strong
等價於使用retain
,而在arc下對block執行retain,會被轉化為objc_blockretain
。
該函式在runtime中是這樣實現的:
//
// the -fobjc-arc flag causes the compiler to issue calls to objc_
//id objc_retainblock
(id x)
綜上所述,在arc下,對block使用strong
等價於使用retain
,而對block使用retain
,會在執行時呼叫_block_copy
,所以這跟使用copy
是一樣的效果。
而將block從棧複製到堆上時,可以防止block
或者block
中使用的變數被釋放。
對block使用copy函式,不管是棧上的、堆上的、全域性的block都不會出現問題。所以,我們就統一使用copy
來修飾了。
Block儲存域學習
時間版本修改 2020年5月9日 初稿2020年5月10日 新增編譯器不能自動將block從棧複製到堆上的情況說明 我試圖從網上找一下 objective c高階程式設計 ios與os x多執行緒和記憶體管理 2.3.4節的圖,發現竟然一張都沒找著,本來還想貼一下圖的,本人虎軀一震,一切都變得索然無...
變數儲存域
變數儲存域 2010 09 23 15 43 1.1 變數儲存域 1.1.1 乙個示例 pang123hui首先提供了乙個網上流傳的學習 示例 int a 0 全域性區 void main int b 棧 char s abc s在棧,abc在文字常量區 char p1,p2 棧 char p3 1...
變數儲存型別 作用域
auto 作用域和壽命 只能做區域性變數 在函式內或復合語句內定義的自動變數可以省略auto,而在外部定義的無auto的變數顯然不是自動變數 外部變數,即 全域性變數 的壽命和作用域是全域性的 register 作用域和壽命 同auto,即 區域性可見 分配通用暫存器的條件 1 有空閒的暫存器 2 ...