【发布时间】:2015-07-31 13:32:15
【问题描述】:
我们的应用程序在我们编写的支持 ARC 的库中遇到了双重发布崩溃。运行检测后,我们发现双重释放发生在一个由 2 个线程访问的对象上。
有问题的对象首先在初始化方法中分配到 2 个线程之外
objectX = [[NSData alloc] initWithBytes:barcodeBytes length:sizeof(barcodeBytes)];
线程 A 启动并将 objectX 添加到 NSDictionary。
线程 B 将 ObjectX 分配给本地 NSData 指针,并使用 removeObjectAtIndex 从共享的 NSDictionary 中删除 ObjectX
我们通过运行 NSZombie 注意到的是,ObjectX 现在被自动释放了两次。似乎一个版本是直接在对象上发布的,而另一个版本是在包含它的 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
最终结果是 ObjectX 被释放了两倍,我们看到了崩溃。有趣的是,我们只在 arm64 设备上看到了这种情况。
【问题讨论】:
标签: objective-c multithreading automatic-ref-counting