2015-05-19 51 views
1

我們的應用程序在我們編寫的啓用了ARC的庫中遇到了雙發佈崩潰。在運行檢測之後,我們發現雙釋放發生在由2個線程訪問的對象上。如何阻止ARC釋放兩個線程共享的對象兩次?

所討論的對象首先在2個線程以外分配在一個初始化方法

objectX = [[NSData alloc] initWithBytes:barcodeBytes length:sizeof(barcodeBytes)]; 

線程A開始,並將其添加到目標x一個NSDictionary。

線程B assignes _對象到本地的NSData指針和使用removeObjectAtIndex

,我們已經通過運行NSZombie注意到的是,目標x目前正在自動釋放兩次從共享的NSDictionary去除_對象。看起來,一個版本直接發佈在對象上,另一個版本是在包含它的NSDictionary被釋放時間接完成的。

首次發行:

0 libobjc.A.dylib -[NSObject release] 
    1 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::pop(void*) 
    2 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::tls_dealloc(void*) 
    3 libsystem_pthread.dylib _pthread_tsd_cleanup 
    4 libsystem_pthread.dylib _pthread_exit 
    5 libsystem_pthread.dylib pthread_exit 
    6 Foundation +[NSThread exit] 
    7 TestApp 0x348e72 
    8 Foundation __NSThread__main__ 
    9 libsystem_pthread.dylib _pthread_body 
    10 libsystem_pthread.dylib _pthread_start 
    11 libsystem_pthread.dylib thread_start 

第二個版本:

0 libobjc.A.dylib -[NSObject release] 
    1 CoreFoundation CFRelease 
    2 CoreFoundation -[__NSDictionaryM dealloc] 
    3 libobjc.A.dylib objc_object::sidetable_release(bool) 
    4 libobjc.A.dylib -[NSObject release] 
    5 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::pop(void*) 
    6 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::tls_dealloc(void*) 
    7 libsystem_pthread.dylib _pthread_tsd_cleanup 
    8 libsystem_pthread.dylib _pthread_exit 
    9 libsystem_pthread.dylib pthread_exit 
    10 Foundation +[NSThread exit] 
    11 TestApp 0x348e72 
    12 Foundation __NSThread__main__ 
    13 libsystem_pthread.dylib _pthread_body 
    14 libsystem_pthread.dylib _pthread_start 
    15 libsystem_pthread.dylib thread_start 

最終的結果是_對象是雙釋放,它更應該有和我們看到的崩潰。有趣的是,我們只在arm64設備上看到這一點。

回答

0

當你在兩個線程中存儲對象時,你也隱含地保留該對象,所以發佈計數匹配。相反,我會看看你是否搞亂了某個地方的線程,特別是如果你不使用GCD。請記住,ARM是一種微弱有序的架構,因此與x86相比,進入內存排序問題要容易得多。

0

線程A啓動並將objectX添加到NSDictionary中。

線程B assignes _對象到本地NSData的指針,並將其從共享的NSDictionary

去除_對象但有你的問題就在這裏。你有兩個對象,objectX和字典,它們被兩個不同的線程觸及。這是一個嚴重的危險,如果你不確切地知道你在做什麼以及如何採取適當的預防措施,你根本不應該這樣做。

+0

你不分享任何關於你的代碼的信息,所以不可能多說。魔鬼在細節中,而你根本沒有提到任何細節。有辦法處理在線程之間傳遞/共享對象,但誰知道你是否在使用它們? – matt

0

沒有看到字典的同步代碼很難說。如果數據不可變,您可以在第二個線程中創建一個副本。這將確保它是一個不同於刪除字典的對象。

另外,請確保在您修改字典時,所有讀取的線程都在等待。

相關問題