Weak Strong Dance 真的安全嗎?

2021-09-11 09:58:32 字數 3686 閱讀 5749

絕大多數ios開發者用過block,並且知道用__weak的方式去解決迴圈引用的問題。而高階一些的開發者則了解weak-strong-dance,那麼什麼是weak-strong-dance?它能保證block執行是的「安全」嗎?

看看下面兩段**的區別,你就明白什麼是weak-strong-dance了。

- (void)test ;

}複製**

- (void)test ;

}複製**

也就是在用__weak解決迴圈引用的前提下 ,在block內部用__strong持有物件,試**決「在多執行緒下,可能weakself指向的物件會在 block 執行前被廢棄,導致各種各樣的問題,比如說kvo,傳入nil可是會crash呢」,如下**

__weak typeof(self) weakself = self;

self.handler = ^;複製**

此時,你可能會這樣認為,self所指向物件的引用計數變成 2,即使主線程中的 self 因為超出作用於而釋放,物件的引用計數依然為 1,避免了物件的銷毀。

它真的能解決在多執行緒下,可能 weakself 指向的物件會在 block 執行前被廢棄而導致的問題嗎?

答案當然是否定的,讓我們來看看demo:

不用weak-strong-dance

#import "testblock.h"

@inte***ce testblock ()

@property (nonatomic, strong) dispatch_block_t block;

@end

@implementation testblock

- (void)test ;

}@end複製**

看看用clang改寫後的**,這裡就只貼關鍵**了:

// @inte***ce testblock ()

// @property (nonatomic, strong) dispatch_block_t block;

/* @end */

// @implementation testblock

struct __testblock__test_block_impl_0

};static

void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself)

static

void __testblock__test_block_copy_0(struct __testblock__test_block_impl_0*dst, struct __testblock__test_block_impl_0*src)

static

void __testblock__test_block_dispose_0(struct __testblock__test_block_impl_0*src)

static struct __testblock__test_block_desc_0 __testblock__test_block_desc_0_data = ;

static

void _i_testblock_test(testblock * self, sel _cmd)

static

void(* _i_testblock_block(testblock * self, sel _cmd) )()

static

void _i_testblock_setblock_(testblock * self, sel _cmd, dispatch_block_t block)

// @end

複製**

**很長,解釋下:

struct__testblock__test_block_impl_0裡頭,我們能看到testblock *const __weak weakself;這代表在block內部是以弱引用的方式捕獲self的,這沒毛病。重點來了,看這一段代表block具體實現的**塊

static

void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself) 複製**

這裡可以看到如果此時外部廢棄了self,的確會導致block內部訪問成nil的情況。

那麼如果用了weak-strong-dance呢?

__weak typeof(self) weakself = self;

self.block = ^;複製**

看看clang改寫後會有什麼區別:

struct __testblock__test_block_impl_0 

};static

void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself) 複製**

區別在於在block內多了這麼一行**__attribute__((objc_ownership(strong))) typeof(self) strongself = weakself;

所以持有self的行為是在block執行的時候才發生的!

回過頭來看看問題:它真的能解決在多執行緒下,可能 weakself 指向的物件會在 block 執行前被廢棄而導致的問題嗎?

在執行前就廢棄,到了執行的時候,weakself已經是nil了,此時執行__strong typeof(self) strongself = weakself;根本沒意義吧。

所以在剛才kvo的例子中,該crash還是繼續crash吧。只要在執行__strong typeof(self) strongself = weakself;前,物件在其他執行緒被廢棄了,weak-strong-dance不能幫上任何忙!

weak-strong-dance並不能保證block所引用物件的釋放時機在執行之後, 更安全的做法應該是在block內部使用strongself時進行nil檢測,這樣可以避免上述情況。

Docker容器真的安全嗎?

本文基於我今年在dockercon上的演講。它將討論docker容器安全性,我們當前的位置以及發展的方向。這是有關docker安全性的系列文章的一部分 請閱讀第二部分 我聽到並讀到很多人都認為docker容器實際上是沙箱應用程式 意味著他們可以使用docker作為根在自己的系統上執行隨機應用程式。他...

linux真的很安全麼?

寫這篇文章是因為看到了cnbeta上最近接二連三地出現類似這篇的文章。雖然我還是認為此文的作者多少還是有點標題黨,因為那個 a 其實可以是任何東西,這樣就說是 乙個命令 也太無聊了點。但是我在公司的rhel4的伺服器上試驗了之後,確實可以非法提公升許可權。不免有點擔憂。於是我順藤摸瓜,在那個提供ha...

你的登入介面真的安全嗎?

大家學寫程式時,第一行 都是hello world。但是當你開始學習web後台技術時,很多人的第乙個功能就是寫的登入 小聲 別人我不知道,反正我是 但是我在和很多任務作經驗較短的同學面試或溝通的時候,發現很多同學雖然都有在簡歷上寫 負責專案的登入 註冊功能模組的開發和設計工作,但是都只是簡單的實現了...