Ответ 1
Поздравляем: вы обнаружили ошибку в 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 > Application > Command Line Tool. Когда вы запускаете свою программу, Xcode должен автоматически показывать приглашение GDB в области отладки. Если область отладки не отображается в стандартном редакторе, выберите "Просмотр" > "Область отладки" > "Показать область отладки".
Изменить: эта ошибка была исправлена в OS X v10.7.3.