恭喜:您在 Core Foundation 中发现了一个错误!
正如比尔怀疑的那样,这与Lion 中的标记指针 http://objectivistc.tumblr.com/post/7872364181/tagged-pointers-and-fast-pathed-cfnumber-integers-in。当你创建时
NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];
d1
并不指向实际的NSNumber
实例。反而,d1
是一个标记指针,包含0x4c3
, where 0x4
是标记指针中的有效负载。
当您尝试使用标记指针作为弱属性的值时,Objective-C 运行时执行的步骤之一是发送-allowsWeakReference
到实例来验证它是否可以用作弱引用。自从NSNumber
不重写该方法,默认实现NSObject
被执行,依次发送_isDeallocating
,这又调用_CFIsDeallocating()
如该堆栈跟踪所示:
#0 0x00007fff8ccdbacd in _CFIsDeallocating ()
#1 0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2 0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3 0x0000000100000ded in main () at test.m:12
如果你读过CFRuntime.c http://www.opensource.apple.com/source/CF/CF-635/CFRuntime.c,你会看到_CFIsDeallocating()
将相应的指针转换为CFRuntimeBase *
为了阅读_cfinfo
。对于普通的 Core Foundation 对象,这是有效的,因为每个常规 Core Foundation 引用都指向一个以isa
指针,后跟_cfinfo
。但是,标记指针并不指向实际(分配的)内存,因此_CFIsDeallocating()
尝试取消引用无效的指针,从而导致分段错误。
你应该向 Apple 提交错误报告 http://bugreport.apple.com。同时,使用strong
or unsafe_unretained
财产。
Edit:要获取回溯,请使用以下命令构建可执行文件-g
包含调试信息,例如:
$ clang test.m -g -fobjc-arc -framework Foundation -o test
并使用 GDB 运行它:
$ gdb test
…
(gdb) run
程序会崩溃:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000004cb
0x00007fff8ccdbacd in _CFIsDeallocating ()
Use the bt
GDB 中获取回溯的命令:
(gdb) bt
#0 0x00007fff8ccdbacd in _CFIsDeallocating ()
#1 0x00007fff8ccd3119 in -[__NSCFNumber _isDeallocating] ()
#2 0x00007fff8be34b15 in -[NSObject(NSObject) allowsWeakReference] ()
#3 0x00007fff875173a6 in weak_register_no_lock ()
#4 0x00007fff875179f9 in objc_storeWeak ()
#5 0x0000000100000c0e in -[Car setDoors:] (self=0x100113f60, _cmd=0x100000e7a, doors=0x4c3) at test.m:8
#6 0x0000000100000d45 in main () at test.m:23
然后是quit
退出GDB的命令:
(gdb) quit
在 Xcode 中,使用 Mac OS X > 应用程序 > 命令行工具模板。当你运行你的程序时,Xcode应该自动在调试区域显示GDB提示符。如果调试区域未显示在标准编辑器中,请选择“视图”>“调试区域”>“显示调试区域”。
Edit:此错误已在 OS X v10.7.3 中修复。