当自动释放池耗尽时,NSFileAttributes dealloc 中的 SIGSEGV SEGV_ACCERR 崩溃?
Posted
技术标签:
【中文标题】当自动释放池耗尽时,NSFileAttributes dealloc 中的 SIGSEGV SEGV_ACCERR 崩溃?【英文标题】:SIGSEGV SEGV_ACCERR crash in NSFileAttributes dealloc when autoreleasepool is drained? 【发布时间】:2012-04-23 23:10:27 【问题描述】:使用 NSFileManager 在后台线程中获取文件大小时,我遇到了奇怪的崩溃。
我有一个名为 localFileSize 的歌曲对象的属性:
- (unsigned long long)localFileSize
return [[[NSFileManager defaultManager] attributesOfItemAtPath:self.currentPath error:NULL] fileSize];
在我处理音频播放的类中(使用第 3 方音频库,而不是 AQS 或 Core Audio),有一个文件长度回调函数在音频库的播放线程中调用,而不是在主线程中调用。
在那个文件长度函数中,我在 @autoreleasepool 中读取我的歌曲对象的 localFileSize 属性。在函数结束时,当池被耗尽时,NSFileAttributes 对象的 dealloc 方法有时会出现崩溃。我自己无法重现它,但我有 14 条与此问题相关的崩溃日志。
以下是其中一个崩溃日志的相关部分:
Thread 8 Crashed:
0 libobjc.A.dylib 0x3262c4e8 _ZN4objc8DenseMapIP11objc_objectmLb1ENS_12DenseMapInfoIS2_EENS3_ImEEE4growEj + 67
1 libobjc.A.dylib 0x32638d81 _ZN4objc8DenseMapIP11objc_objectmLb1ENS_12DenseMapInfoIS2_EENS3_ImEEE16InsertIntoBucketERKS2_RKmPSt4pairIS2_mE + 56
2 libobjc.A.dylib 0x3262b09d _ZN4objc8DenseMapIP11objc_objectmLb1ENS_12DenseMapInfoIS2_EENS3_ImEEE16FindAndConstructERKS2_ + 44
3 libobjc.A.dylib 0x3262b139 _objc_rootReleaseWasZero + 92
4 libobjc.A.dylib 0x3262b0ad _objc_rootRelease + 12
5 Foundation 0x31fbab81 -[NSFileAttributes dealloc] + 60
6 libobjc.A.dylib 0x3262b0c5 _objc_rootRelease + 36
7 libobjc.A.dylib 0x3262cdb7 objc_release + 38
8 libobjc.A.dylib 0x3262be0d _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 224
9 libobjc.A.dylib 0x3262bd29 _objc_autoreleasePoolPop + 12
10 CoreFoundation 0x35b0ce8f _CFAutoreleasePoolPop + 18
11 Foundation 0x31f8aaf1 -[NSAutoreleasePool drain] + 128
12 iSub 0x000fb6cb MyFileLenProc (AudioEngine.m:320)
13 iSub 0x001623d8 BASS_FX_TempoCreate + 5160
14 iSub 0x0016261c BASS_FX_TempoCreate + 5740
15 iSub 0x0017f42c BASS_ChannelIsActive + 27424
16 AudioToolbox 0x364905d9 _ZN19AudioConverterChain19DirectCallInputProcEPmS0_P15AudioBufferListPPK28AudiostreamPacketDescription + 228
17 AudioToolbox 0x36465ee3 _ZN14CodecConverter13CallInputProcERm + 266
18 AudioToolbox 0x3646588d _ZN14CodecConverter17DecoderFillBufferERmR15AudioBufferListP28AudioStreamPacketDescription + 576
19 AudioToolbox 0x36465649 _ZN14CodecConverter10FillBufferERmR15AudioBufferListP28AudioStreamPacketDescription + 28
20 AudioToolbox 0x36452c99 _ZN19AudioConverterChain12RenderOutputEP12CABufferListmRmP28AudioStreamPacketDescription + 92
21 AudioToolbox 0x36452b53 _ZN22BufferedAudioConverter10FillBufferERmR15AudioBufferListP28AudioStreamPacketDescription + 186
22 AudioToolbox 0x36452929 AudioConverterFillComplexBuffer + 356
23 iSub 0x0017d9f8 BASS_ChannelIsActive + 20716
24 iSub 0x00184f70 BASS_ChannelSetPosition + 640
25 iSub 0x00186eb4 BASS_ChannelGetData + 1032
26 iSub 0x000fc787 __35-[AudioEngine keepRingBufferFilled]_block_invoke_0 (AudioEngine.m:752)
27 libdispatch.dylib 0x35e3fd55 _dispatch_call_block_and_release + 12
28 libdispatch.dylib 0x35e4b7a3 _dispatch_worker_thread2 + 262
29 libsystem_c.dylib 0x30fbb1cf _pthread_wqthread + 294
任何想法可能导致这种情况?
此外,如果有任何不同,在报告这些崩溃时,该项目并未使用 ARC。我最近转换为 ARC,但尚未发布更新。无论如何,我认为在这种情况下不会有任何不同。
此外,值得注意的是,所有崩溃报告都来自 iOS 5.0.1 和 5.1,即使我的应用支持 4.2 及更高版本。那么可能是某种 iOS 5 错误?
【问题讨论】:
【参考方案1】:我想知道这种变化是什么时候发生的?我清楚地记得 [NSFileManager defaultManager] 不是线程安全的。而且,顺便说一句,我们也遇到了从多个线程调用 defaultManager 的相同问题。看起来其他人也记得它:http://useyourloaf.com/blog/2011/06/12/nsfilemanager-defaultmanager-is-not-thread-safe.html
【讨论】:
嗯,不知道。但无论如何,我转而使用 C 函数来获取文件信息,从那时起就没有任何问题。【参考方案2】:不要在后台线程中使用这是错误的。+defaultManager
。只需 alloc+init 一个实例,使用它,然后(如果不使用 ARC)释放它。
【讨论】:
真的吗? developer.apple.com/library/ios/#documentation/Cocoa/Reference/… 表示“可以从多个线程安全地调用共享的NSFileManager
对象的方法。”【参考方案3】:
最终使用类似的方法来获取文件大小:
#include <sys/stat.h>
struct stat fileInfo;
off_t fileSize; // Can cast to long long
stat(filename, &fileInfo);
fileSize = fileInfo.st_size;
或者您可以尝试创建新的 NSFileManager 对象,因为文档可能并不完全真实地说明线程安全。
【讨论】:
以上是关于当自动释放池耗尽时,NSFileAttributes dealloc 中的 SIGSEGV SEGV_ACCERR 崩溃?的主要内容,如果未能解决你的问题,请参考以下文章