Понимание дампа malloc_history - PullRequest
9 голосов
/ 06 декабря 2010

Если вы когда-нибудь спрашивали, как я могу отладить проблемы освобождения / выделения ресурсов в target-c, вы столкнетесь с такими настройками среды, которые могут помочь отследить проблему:

  • NSZombieEnabled -Сохраняет абстракции после выпуска, поэтому вы можете получать указатели и т. Д.
  • MallocStackLogging - сохраняет историю объектов для справки позже
  • NSDebugEnabled

Вы установили всеиз них на YES в разделе «среда» вкладки «аргументы» в информации «исполняемые файлы» (находится в дереве групп).


Итак, я получаювывод этой консоли

MyApp [ 4413 : 40b] - [CALayer retainCount]: сообщение отправлено освобожденному экземпляру 0x4dbb170

затем откройте терминал, в то время как отладчик переадресовал перерыв и введите:

malloc_history 4413 0x4dbb170

Затем я получаю большой текстовый дампи, насколько я понимаю, важный бит таков:

1

ALLOC 0x4dbb160-0x4dbb171 [size=18]:
thread_a0375540 |start | main |
UIApplicationMain | GSEventRun |
GSEventRunModal | CFRunLoopRunInMode |
CFRunLoopRunSpecific | __CFRunLoopRun
| __CFRunLoopDoTimer |
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
| __NSFireDelayedPerform |
-[todoListViewController drillDocumentMenu:] |
-[documentListViewController drillIntoDocumentWithToDoRecord:] |
-[documentViewController OpenTodoDocument:OfType:WithPath:] |
-[documentViewController OpenDocumentOfType:WithPath:] |
-[documentViewController managePDFDocumentWithPath:] |
-[PDFDocument loadPDFDocumentWithPath:andTitle:] |
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction |
ListDictionaryObjects(char const*,
CGPDFObject*, void*) | NSLog | NSLogv
| _CFLogvEx | __CFLogCString |
asl_send | _asl_send_level_message |
asl_set_query | strdup | malloc |
malloc_zone_malloc 

2

FREE  0x4dbb160-0x4dbb171 [size=18]:
thread_a0375540 |start | main |
UIApplicationMain | GSEventRun |
GSEventRunModal | CFRunLoopRunInMode |
CFRunLoopRunSpecific | __CFRunLoopRun
| __CFRunLoopDoTimer |
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
| __NSFireDelayedPerform |
-[todoListViewController drillDocumentMenu:] |
-[documentListViewController drillIntoDocumentWithToDoRecord:] |
-[documentViewController OpenTodoDocument:OfType:WithPath:] |
-[documentViewController OpenDocumentOfType:WithPath:] |
-[documentViewController managePDFDocumentWithPath:] |
-[PDFDocument loadPDFDocumentWithPath:andTitle:] |
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction |
ListDictionaryObjects(char const*,
CGPDFObject*, void*) | NSLog | NSLogv
| _CFLogvEx | __CFLogCString |
asl_send | _asl_send_level_message |
asl_free | free

3

ALLOC 0x4dbb170-0x4dbb19f [size=48]:
thread_a0375540 |start | main |
UIApplicationMain | GSEventRun |
GSEventRunModal | CFRunLoopRunInMode |
CFRunLoopRunSpecific | __CFRunLoopRun
| __CFRunLoopDoTimer |
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
| __NSFireDelayedPerform |
-[todoListViewController drillDocumentMenu:] |
-[documentListViewController drillIntoDocumentWithToDoRecord:] |
-[documentViewController OpenTodoDocument:OfType:WithPath:] |
-[documentViewController OpenDocumentOfType:WithPath:] |
-[documentViewController managePDFDocumentWithPath:] |
-[ScrollViewWithPagingViewController init] | -[UIView init] |
-[UIScrollView initWithFrame:] | -[UIView initWithFrame:] | UIViewCommonInitWithFrame | -[UIView
_createLayerWithFrame:] | +[NSObject(NSObject) alloc] | +[NSObject(NSObject) allocWithZone:] | class_createInstance |
_internal_class_createInstanceFromZone | calloc | malloc_zone_calloc

Чего я не понимаю, так это если история была ALLOC, FREE, ALLOC, то почему ошибка указывает, что она была выпущена (net +1 alloc)?

или мое понимание дампов неверно?


РЕДАКТИРОВАТЬ (новый запуск = разные указатели объектов):

Обнаружение зомби с помощью инструментов:

Ответы [ 2 ]

2 голосов
/ 06 декабря 2010

@ Кей правильный;история malloc показывает два размещения по указанному адресу;тот, который был выделен и освобожден, и тот, который все еще находится в игре.

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

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

Я бы предложил работать с обнаружением зомби в Инструментах.Надеюсь, это точно определит точную проблему.

Если нет, то есть точка останова, которую можно установить, чтобы сломать, когда зомби сообщается.Установите эту точку останова и посмотрите, где вы остановитесь.

ОК - так, CoreAnimation использует счет сохранения для внутренних целей (системные рамки могут с этим справиться, хотя и хрупкими). ​​

Я думаю, что -1 - красная сельдь;вполне вероятно, что зомби вернут 0xFF .... FFFF в качестве счетчика сохраняемых значений, и в инструментах это значение равно -1.

Следующая лучшая догадка;поскольку это происходит по таймеру, переиздание, вероятно, происходит во время анимации.Слои CoreAnimation должны обрабатывать это правильно.В вашем коде есть чрезмерный выпуск контейнера слоя представления или анимации, из-за которого слой преждевременно исчезает.

Вы пробовали "Построить и проанализировать"?Неслучайно это могло бы поймать неумелое управление представлением где-нибудь.

В любом случае и в качестве эксперимента попробуйте сохранить свое представление в течение дополнительного времени и посмотреть, остановит ли это эту проблему.Если это так, то это, по крайней мере, ключ.

(Или это может быть ошибка в системных рамках ... может быть ... но сомнительно.)

Наконец, кто, черт возьми, звонит retainCount?!?!? В случае CoreAnimation, возможно, что retainCount используется внутри как деталь реализации.

Если этохотя ваш код, тогда местоположение вызова зомби должно быть довольно очевидным.

0 голосов
/ 06 декабря 2010

Я не эксперт, но если вы посмотрите на первую строку в блоке 3:

ALLOC 0x4dbb170 -0x4dbb19f [размер = 48 ]:

В то время как в двух других выходах был выделен и освобожден блок памяти размером 18 в 0x4dbb160-0x4dbb171. Я предполагаю, что старый объект был освобожден, и есть новый объект, находящийся по этому адресу памяти. Таким образом, старый экземпляр в 0x ... b160 больше не действителен.

...