0

我有需要的塊的方法,包括:複製的塊和CLANG泄漏警告

- (void)methodWithBlock:(blockType)block 

的方法,通過複製block開始時,因爲它在使用前不異步事,它會被其他方式丟棄。然後它調用另一個塊內的方法,然後在該塊內釋放它。總結:

- (void)methodWithBlock:(blockType)block 
{ 
    block = [block copy]; 
    [something asyncStuffWithFinishedBlock:^{ 
     // .. 
     block(); 
     [block release]; 
    }]; 
} 

CLANG抱怨「塊」的內存泄漏。如果我刪除了複製和釋放語句,塊會在被調用的時候消失 - 至少早些時候崩潰表明這是事實。

這是錯誤的做法嗎?如果是這樣,我應該如何做上述 - 即方法中的塊語句中的塊回調?我不能將塊存儲爲一個實例變量,因爲在異步部分發生時可以用不同的參數重複調用該方法。

回答

3

首先,-copy-release應該是不必要的。方法-asyncStuffWithFinishedBlock:必須複製傳遞給它的塊。當一個塊被複制並且引用其他塊對象時,它也複製這些塊對象。你需要弄清楚你所看到的崩潰的真實性質。

其次,你發佈了錯誤的東西。 [block copy]不會修改block-copy消息的接收者)以某種方式將其變爲副本。它返回該塊的副本。這是您要在調用語句(block();)和釋放時引用的返回副本。

所以,你可以這樣做:

block = [block copy]; 
[something asyncStuffWithFinishedBlock:^{ 
    // .. 
    block(); 
    [block release]; 
}]; 

注意局部變量block的重新分配,使其指向該副本。

想想這樣:你會複製一個字符串的方式,你試圖複製該塊?你會怎麼做:

[someString copy]; 
// ... use someString ... 
[someString release]; 
+0

哎呀,我錯了 - 我的意思是塊= [塊複製]在該聲明。 – Kalle

+0

至於他們是不必要的......嘎。好的,謝謝我會做一些研究。 – Kalle

1

我不認爲你應該做的release像塊內。你假設塊被調用一次。但僅僅從代碼中,我們不知道這一點。這可能是該方法根本不執行該塊,在這種情況下,您將不會釋放,因此泄漏。也可能是該方法多次執行該塊,在這種情況下,您會過度釋放。

如果你真的想複製它,你需要釋放外塊這樣的(保留的東西應該負責釋放它的範圍):

- (void)methodWithBlock:(blockType)block 
{ 
    block = [block copy]; 
    [something asyncStuffWithFinishedBlock:^{ 
     // .. 
     block(); 
    }]; 
    [block release]; 
} 

(這是不相關的東西asyncStuffWithFinishedBlock力量來與它的參數;根據內存管理規則,如果需要圍繞保持更長的時間,它需要保留或複製它(它需要複製塊))爲

然而,肯·托馬斯指出。因爲你不在任何地方存儲塊,所以你不需要在這個方法中複製它。 asyncStuffWithFinishedBlock應該複製它的參數塊,如果它需要異步運行的話;並且該塊所捕獲的任何塊在複製時都應該被複制。

+0

我忘了提,但是,塊是一次性的東西,這是重置。 – Kalle