Поздравляем: вы нашли ошибку в Core Foundation!
Как подозревал Билл, это связано с помеченными указателями в Lion . Когда вы создаете
NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4];
d1
не указывает на фактический NSNumber
экземпляр. Вместо этого d1
- это тегированный указатель, содержащий 0x4c3
, где 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 , вы увидите, что _CFIsDeallocating()
приводит соответствующий указатель к CFRuntimeBase *
для чтения _cfinfo
. Для обычных объектов Core Foundation это работает, потому что каждая обычная ссылка на Core Foundation указывает на экземпляр, который начинается с указателя isa
, за которым следует _cfinfo
. Однако теговые указатели не указывают на фактическую (выделенную) память, поэтому _CFIsDeallocating()
пытается разыменовать недопустимый указатель, отсюда и ошибка сегментации.
Вы должны подать отчет об ошибке в Apple . Тем временем используйте свойство strong
или unsafe_unretained
.
Редактировать: , чтобы получить обратную трассировку, соберите свой исполняемый файл с -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 ()
Используйте команду 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 в области отладки. Если область отладки не отображается в стандартном редакторе, выберите «Просмотр»> «Область отладки»> «Показать область отладки».
Редактировать: эта ошибка была исправлена в OS X v10.7.3.