Objective-C - ARC - NSNumber - Ошибка сегментации - PullRequest
10 голосов
/ 14 ноября 2011

У меня есть программа Objective-C, и я использую ARC (автоматический подсчет ссылок), он выдает ошибку сегментации в строке 23 (см. Программу ниже).

Вопрос 1) Почему возникает ошибка сегментации?

Ниже приведена программа:

#import<Foundation/Foundation.h>

@interface Car : NSObject
@property (weak) NSNumber* doors;
@end

@implementation Car 
@synthesize doors;
@end

int main()
{
    system("clear");

    @autoreleasepool
    {    
        Car *car1 = [[Car alloc] init];

        printf("1\n");
        NSNumber *d1 = [[NSNumber alloc] initWithInteger: 4]; 

        printf("2\n");
        car1.doors = d1;   //Segmentation fault.. why ?

        printf("3\n");
    }   

    printf("---- end\n");

    return(0);
}

Выход:

1
2
Segmentation fault: 11

Ответы [ 2 ]

23 голосов
/ 15 ноября 2011

Поздравляем: вы нашли ошибку в 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.

0 голосов
/ 14 ноября 2011

Опубликовать обратную трассировку. Также - какая платформа?

Это может быть ошибка, связанная с NSNumber и теговыми указателями (если используется 64-разрядная версия OS X).

...