Проблема:
Предполагаемый сбой в сборщике мусора.
Вопрос:
Как вы справляетесь с этим?
Могу ли я что-нибудь ещекроме подачи сообщения об ошибке?Очевидным решением было бы: «не изменяйте размер представления», но это слишком повредило бы функциональности.Было бы полезно предотвратить перерисовку представлений до завершения изменения размера?Я попытался [… removeFromSuperView], затем изменил размер, затем [… addSubView:…];Это не помогает
Как можно избежать / избежать этой проблемы?
Сообщение об ошибке:
malloc: garbage block 0x2008a71a0(_NSClipViewBackingLayer[128]) was over-retained during finalization, refcount = 1
This could be an unbalanced CFRetain(), or CFRetain() balanced with -release.
Break on auto_zone_resurrection_error() to debug.
malloc: fatal resurrection error for garbage block 0x2008a71a0(_NSClipViewBackingLayer[128]): over-retained during finalization, refcount = 1
Сбой потока является фоновым потоком из сборщика мусора, который называется "Мусор".Очередь сбора работ ".
Когда я ломаю auto_zone_resurrection_error и выполняю трассировку стека, я получаю:
0 0x00007fff8094aba4 in auto_zone_resurrection_error ()
1 0x00007fff80959ce6 in Auto::Zone::handle_overretained_garbage ()
2 0x00007fff8095a0b4 in Auto::Zone::free_garbage ()
3 0x00007fff80944bd3 in auto_collect_internal ()
4 0x00007fff809450cd in auto_collection_work ()
5 0x00007fff80626284 in _dispatch_call_block_and_release ()
6 0x00007fff80604df2 in _dispatch_queue_drain ()
7 0x00007fff80604c54 in _dispatch_queue_invoke ()
8 0x00007fff806047fe in _dispatch_worker_thread2 ()
9 0x00007fff80604128 in _pthread_wqthread ()
10 0x00007fff80603fc5 in start_wqthread ()
Я подозреваю, что проблема связана с IKImageViews, размер которых изменяется.Почему я подозреваю это?
Укрощение IKImageView было королевской PITA от начала до конца (недостаточно документировано, содержит ошибки, множество функций, но нет доступа к ним).
Сбой происходит во время изменения размера NSScrollView с 3 IKImageViews.
Основной поток останавливается при [IKImageView zoomImageToFit:]
Обновление в ответ на @bbum и @Peter Hosey
Мне не удалось исправить, но в основном обойти сбой сборщика мусора.
- Включено: MallocStackLoggingNoCompact AUTO_REFERENCE_COUNT_LOGGING
- перерыв в auto_zone_resurrection_error
- получить адрес избыточного блока (в данном случае 0x20242cde0, только для ссылки на ниже)
info mallocЗатем 0x20242cde0 произвел много выходных данных по этому адресу (290 КБ простого текста).Наиболее частым упоминанием было: NSView _recursiveDisplayRectIfNeededIgnoringOpacity: isVisibleRect: rectIsVisibleRectForView: topView
Как я и ожидал, что-то происходило во время рисования NSView.
Я впоследствии попробовал Instruments, как предложено @Peter.Это производит довольно длинную историю выделенных объектов.Мне нужно было просмотреть отчет о сбое, чтобы получить адрес чрезмерно сохраненного блока (во время работы Instruments вывод на консоль отсутствует, и Instruments не сразу указывают, какой блок нарушает работу (или я не знаю, гдепосмотрите, что вполне возможно)).
# Object Address Category Creation Time Live Size Responsible Library Responsible Caller
659531 0x20242cde0 CFRunLoopObserver 00:21.577.876 128 AppKit -[NSApplication setWindowsNeedUpdate:]
659532 0x20242cde0 Malloc 128 Bytes 00:26.352.081 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659533 0x20242cde0 Malloc 128 Bytes 00:26.352.328 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659534 0x20242cde0 Malloc 128 Bytes 00:26.351.892 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659535 0x20242cde0 Malloc 128 Bytes 00:26.321.389 128 QuartzCore CA::Transaction::add_root(CALayer*)
659536 0x20242cde0 Malloc 128 Bytes 00:26.321.380 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659537 0x20242cde0 Malloc 128 Bytes 00:26.351.710 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659538 0x20242cde0 Malloc 128 Bytes 00:26.320.100 128 QuartzCore CA::Transaction::add_root(CALayer*)
659539 0x20242cde0 Malloc 128 Bytes 00:26.351.433 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659540 0x20242cde0 _NSClipViewBackingLayer 00:26.293.575 • 128 AppKit -[NSClipView makeBackingLayer]
659541 0x20242cde0 Malloc 128 Bytes 00:26.293.601 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659542 0x20242cde0 Malloc 128 Bytes 00:26.351.311 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659543 0x20242cde0 Malloc 128 Bytes 00:26.294.761 • 128 QuartzCore CAViewSetLayer
659544 0x20242cde0 Malloc 128 Bytes 00:26.294.764 • 128 QuartzCore CA::Context::set_layer(CALayer*)
659545 0x20242cde0 Malloc 128 Bytes 00:26.294.767 • 128 QuartzCore CA::Transaction::add_root(CALayer*)
659546 0x20242cde0 Malloc 128 Bytes 00:26.320.091 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659547 0x20242cde0 Malloc 128 Bytes 00:26.347.524 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659548 0x20242cde0 NSConcreteNotification 00:20.730.342 64 Foundation +[NSConcreteNotification newTempNotificationWithName:object:userInfo:]
659549 0x20242cde0 CFNumber 00:16.433.727 32 Foundation -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
659550 0x20242cde0 NSRectSet 00:20.750.542 64 AppKit -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
659551 0x20242cde0 Malloc 128 Bytes 00:21.189.518 128 Foundation -[NSMutableIndexSet _ensureRangeCapacity:]
659552 0x20242cde0 Malloc 128 Bytes 00:26.322.017 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659553 0x20242cde0 Malloc 128 Bytes 00:26.356.013 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659554 0x20242cde0 Malloc 128 Bytes 00:26.356.440 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659555 0x20242cde0 Malloc 128 Bytes 00:26.404.886 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659556 0x20242cde0 Malloc 128 Bytes 00:26.404.887 128 QuartzCore CA::Transaction::add_root(CALayer*)
659557 0x20242cde0 Malloc 128 Bytes 00:26.356.824 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659558 0x20242cde0 Malloc 128 Bytes 00:26.299.972 128 QuartzCore CALayerCollectAllLayers(X::List<CALayer*>*, CALayer*, CA::Transaction*, x_heap_struct*)
659559 0x20242cde0 Malloc 128 Bytes 00:26.322.025 128 QuartzCore CA::Transaction::add_root(CALayer*)
659560 0x20242cde0 CFString (store) 00:23.702.683 128 CoreUI CUIRenderer::CreateImage(long, CUIDescriptor const*, CGRect*, double*, unsigned short*, unsigned char*)
659561 0x20242cde0 Malloc 128 Bytes 00:26.334.571 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659562 0x20242cde0 Malloc 128 Bytes 00:26.332.018 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659563 0x20242cde0 Malloc 128 Bytes 00:26.357.443 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659564 0x20242cde0 Malloc 128 Bytes 00:26.322.144 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659565 0x20242cde0 Malloc 128 Bytes 00:26.322.150 128 QuartzCore CA::Transaction::add_root(CALayer*)
659566 0x20242cde0 Malloc 128 Bytes 00:26.315.651 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659567 0x20242cde0 Malloc 128 Bytes 00:26.333.920 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659568 0x20242cde0 CFString 00:15.204.217 32 Foundation -[NSPlaceholderString initWithFormat:locale:arguments:]
659569 0x20242cde0 Malloc 128 Bytes 00:26.313.695 128 QuartzCore CALayerCollectLayers_(CALayer*, _CALayerIvars*, collect_layers_closure*)
659570 0x20242cde0 Malloc 128 Bytes 00:26.588.328 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659571 0x20242cde0 Malloc 128 Bytes 00:26.325.239 • 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659572 0x20242cde0 Malloc 128 Bytes 00:26.367.861 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659573 0x20242cde0 Malloc 128 Bytes 00:26.325.742 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659574 0x20242cde0 Malloc 128 Bytes 00:26.333.519 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659575 0x20242cde0 Malloc 128 Bytes 00:26.361.547 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659576 0x20242cde0 Malloc 128 Bytes 00:26.367.493 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659577 0x20242cde0 Malloc 128 Bytes 00:26.333.125 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659578 0x20242cde0 Malloc 128 Bytes 00:26.362.011 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659579 0x20242cde0 CFBasicHash 00:16.269.569 64 Foundation +[NSBundle preferredLocalizationsFromArray:forPreferences:]
659580 0x20242cde0 Malloc 128 Bytes 00:26.362.442 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659581 0x20242cde0 Malloc 128 Bytes 00:22.918.104 128 libauto.dylib Auto::foreach_block_do(auto_zone_cursor*, void (*)(void*, void*), void*)
659582 0x20242cde0 Malloc 128 Bytes 00:26.326.245 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659583 0x20242cde0 Malloc 128 Bytes 00:26.363.024 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659584 0x20242cde0 Malloc 128 Bytes 00:26.326.401 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659585 0x20242cde0 CFString (store) 00:16.808.912 128 Foundation -[NSPlaceholderString initWithFormat:locale:arguments:]
659586 0x20242cde0 Malloc 128 Bytes 00:26.326.792 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659587 0x20242cde0 Malloc 128 Bytes 00:26.367.083 128 QuartzCore CALayerTransactionFlagsLocation_(CALayer*, CA::Transaction*, _CALayerIvars*)
659588 0x20242cde0 CFString (store) 00:22.935.991 128 CoreUI CUIRenderer::CreateImage(long, CUIDescriptor const*, CGRect*, double*, unsigned short*, unsigned char*)
659589 0x20242ce00 Malloc 128 Bytes 00:20.100.480 128 Foundation allocateCollectableUnscannedWeakStorageWithSentinel
Объект не был чрезмерно сохранен в моем коде, что затрудняло точное определение того, что и где происходило неправильно.Однако из вышесказанного стало ясно, что во время Core Animation что-то идет не так.
Я заметил, что проще всего воспроизвести сбой, когда я несколько раз изменил размер окна, то есть увеличил его, а затем несколько увеличил.Я подозреваю, что сбой вызван вторым изменением размера, происходящим, в то время как IKImageViews в NSScrollView все еще анимируют свое содержимое в ответ на первое изменение размера.
Частичное «решение»:
Я уже не был LiveResizing, но обновлял scrollview после изменения размера окна.
Теперь я блокирую изменение размераглавное окно в течение 1 секунды после каждого windowDidEndLiveResize.Это сильно уменьшает частоту возникновения аварии, но, к сожалению, не полностью устраняет ее.
(Длительность анимации IKImageView составляет около 300 мсек, но блокирование изменения размера на слишком короткую длительность неэффективно. Предполагаемый GC активен в течение некоторого времени после завершения анимации).
Вопрос: можно ли полностью отключить анимацию в IKImageView?
Я попробовал недокументированный закрытый метод [someIKImageView setAnimates: NO], но это ничего не делает.
ПочемуРазве это не полностью устраняет сбой?
Я худойk, потому что я все еще могу вызвать уведомления об изменении размера, даже если я (пытаюсь) заблокировать изменение размера окна (временно скрывая глиф изменения размера и фиксируя максимальный / минимальный размер).
Вопрос: Есть ли лучший способ предотвратить изменение размера окна?
(Я читаю этот блог: vgable.com / blog / 2008/04/11 / nswindow-setresizable )
[PS 1: информация gc-root 0x20242cde0 просто зависнет (я ждал 10 минут; никакого вывода; приглашение никогда не возвращалось).]
[PS 2: это также было полезно (сайт @bbum) using-malloc-to-debug-memory-misuse-in-cocoa ]