2012-07-23 39 views
1

邁克·阿什說:__bridge_transfer的相關描述;它是否避免了雙重保留?

當__bridge_transfer在鑄造時,它告訴ARC這個對象已經保留,而ARC不需要再保留它。自從ARC獲得所有權後,它在完成後仍會釋放它。

鏘文檔說:

(__bridge_transfer T)運算連鑄操作數,其必須具有非可保持指針類型,到目的地的類型,它必須是一個可保持對象指針類型。 ARC將在封閉的完整表達式的末尾釋放該值,這取決於對本地值的通常優化。

沒有在Clang文檔中說它__bridge_transfer避免了雙重保留。它只是表示該對象將在未來某個時間發佈。

這是爲什麼?考慮以下代碼片段:

NSString *value = (__bridge_transfer NSString *)CFPreferencesCopyAppValue(CFSTR("someKey"), CFSTR("com.company.someapp")); 

CFStringRef從retainCount +1開始。將其分配給值時,CFStringRef會再次被保留,因爲默認情況下,會強烈引用value。這導致了雙重保留。在範圍的最後,一個-release被髮送到value,但是沒有其他任何東西可以平衡CFPreferences * 複製 * AppValue的滯留,從而導致內存泄漏。

__bridge_transfer如何避免雙保留?

回答

1

Clang的文檔與Mike Ash一致。它表示它執行強制轉換,並且該對象在範圍的末尾釋放。在演員陣容中沒有保留。

基本上,(__bridge_transfer T)導致價值被當作T類型的已經擁有的價值,只是如何調用[T new]將返回T類型的已經擁有的價值。

+0

Clang的文檔並不會說「當__bridge_transfer用於演員時,它告訴ARC此對象已被保留,並且ARC不需要再保留它「。這意味着存在一些內置智能,ARC認識到我們即將分配給強引用類型,並隨後吃掉-retain消息以避免雙重保留。它是否正確? – 2012-07-23 21:42:40

+0

爲了補充一點,是的,我同意在演員陣容上不會執行任何保留。但是在賦值爲'value'時會出現保留。 – 2012-07-23 21:44:46

+0

@nessup:我應該澄清一下:Clang文檔明確聲明該值將在完整表達式的末尾釋放。這基本上意味着「這是一個擁有的價值」。演員陣容中沒有保留,但之後有一個釋放。隨後分配給局部變量將保留第二次,但當該變量超出範圍時也會有第二次釋放。優化器將識別雙重保留並將其刪除,因此您將剩下一個保留(並且在該範圍末尾有一個單獨的版本)。 – 2012-07-23 22:08:45

0

當你使用「transfer」時,ARC會在對象保留計數結束時遞減對象 - 所以在這種情況下,你從1開始計數,「value」很強,所以它增加了計數,但是「傳遞」 導致的減量所以你最終回用1

NSString *value = (__bridge_transfer NSString *)CFStringCreateMutableCopy(NULL, 1000, CFSTR("Hello World")); 
NSLog(@"value retainCount %ld", CFGetRetainCount((__bridge CFTypeRef)value)); 
NSLog(@"Value = %@", value); 

2012-07-23 17:45:49.421 TimeTester [75918:F803]值retainCount 1 2012-07-23 17:45 :49.423 TimeTester [75918:f803] Value = Hello World

+0

您對實際發生的行爲的描述絕對正確。那麼,在我看來,Mike Ash的推薦實際上導致了內存泄漏,因爲沒有任何東西可以平衡來自CreateMutablyCopy的+1 ... – 2012-07-23 21:53:27

+1

檢查出http://www.mikeash.com/pyblog/friday-qa-2011- 09-30-automatic-reference-counting.html。 「__bridge_transfer註解解決了這個問題」的Cmd + F。 – 2012-07-23 21:54:14