Сбой NSDictionary allKeys - не удается понять обстоятельства отчета о сбое

У меня есть следующий код:

- (Item *) getRandomItem {
    if (itemIDs == nil) {
        [self parse];
    }
    NSArray * allKeys = [allItems allKeys];
    int seed = arc4random()%[allKeys count];
    return [self getItemByID:[allKeys objectAtIndex:seed]];
}

Иногда происходит сбой в живом приложении, но мы не можем воспроизвести сбой. Я пытался проанализировать отчет и понять, что может быть причиной сбоя, но безуспешно. В любом случае, когда я пытаюсь подделать объект allItems, чтобы вызвать сбой, это приводит к ошибке, отличной от той, о которой сообщается здесь.

Мне нужна помощь в понимании того, при каких обстоятельствах может произойти следующий сбой:

Hardware Model:      iPhone3,1
Code Type:       ARM (Native)
Parent Process:  launchd [1]
OS Version:      iPhone OS 5.0.1 (9A405)
Report Version:  104
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000010
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3427eb30 _class_isInitialized
1   libobjc.A.dylib                 0x3427e8d6 _class_initialize
2   libobjc.A.dylib                 0x3427e88e prepareForMethodLookup
3   libobjc.A.dylib                 0x3427e76a lookUpMethod
4   libobjc.A.dylib                 0x3427e008 objc_msgSend_uncached
5   CoreFoundation                  0x33f7c020 CFRetain
6   CoreFoundation                  0x33f85bac +[__NSArrayI __new::]
7   CoreFoundation                  0x33f85ac6 -[__NSPlaceholderArray initWithObjects:count:]
8   CoreFoundation                  0x33f85806 +[NSArray arrayWithObjects:count:]
9   CoreFoundation                  0x33fa0e92 -[NSDictionary allKeys]
10  AClockworkBrain                 0x0008f46e -[ItemManager getRandomItem] (ItemManager.m:360)
......

Спасибо.


person dimitrios    schedule 06.03.2012    source источник
comment
Вы используете ARC или нет? Кажется, это ошибка, связанная с памятью.   -  person Richard J. Ross III    schedule 06.03.2012
comment
Подождите, вы пытаетесь добавить в свой словарь необработанное целое число? Вы пытаетесь отправить сообщение объекту в памяти 0x10, что похоже на обычное целое число в вашем приложении.   -  person Richard J. Ross III    schedule 06.03.2012
comment
Ричард, мы не используем ARC.   -  person dimitrios    schedule 06.03.2012


Ответы (1)


Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3427eb30 _class_isInitialized
1   libobjc.A.dylib                 0x3427e8d6 _class_initialize
2   libobjc.A.dylib                 0x3427e88e prepareForMethodLookup
3   libobjc.A.dylib                 0x3427e76a lookUpMethod
4   libobjc.A.dylib                 0x3427e008 objc_msgSend_uncached
5   CoreFoundation                  0x33f7c020 CFRetain
6   CoreFoundation                  0x33f85bac +[__NSArrayI __new::]
7   CoreFoundation                  0x33f85ac6 -[__NSPlaceholderArray initWithObjects:count:]

Этот сбой является признаком чрезмерного выпуска или повреждения. В частности, один из ключей в вашем словаре был перевыпущен и/или поврежден. В частности, указатель isa теперь указывает на мусор.

Когда allKeys пытается создать временный массив всех ключей, он пытается сохранить поврежденный объект (через CFRetain, но обрабатывает это как вызов retain). Среда выполнения не распознает указатель isa как инициализированный класс (поскольку он указывает на мусор) и пытается вызвать initialize для этого «класса», что приводит к сбою.

Так получилось, что поврежденное isa, вероятно, является значением, указывающим на читаемое, но мусорное меню, и это приводит к сбою на нескольких уровнях в глубине среды выполнения. Чаще всего это происходит из-за того, что объект был перевысвобожден, а затем какая-то структура была подвергнута функции malloc() в том же месте, и эта структура имеет указатель в качестве первой записи, что является совершенно распространенным шаблоном для структур.

Исправить?

Сначала запустите анализатор и исправьте все проблемы, на которые он жалуется.

Затем проверьте все случаи использования объектов, которые являются ключами в этом словаре. Посмотрите, сможете ли вы найти, где может произойти избыточный выпуск.

Наконец, попробуйте включить зомби и посмотреть, сможете ли вы воспроизвести сбой.

person bbum    schedule 06.03.2012
comment
bbum спасибо за такой подробный ответ. Я не владею всей этой низкоуровневой информацией, но, похоже, вы ее знаете. Мы внимательно изучим это. Спасибо еще раз! - person dimitrios; 07.03.2012
comment
Этот сбой произошел со мной, потому что я вызвал [myDict allKeys] в потоке, отличном от того, в котором управлялись объекты. Как говорится в этом ответе, это были указатели на освобожденные объекты. - person stevel; 27.02.2014