Как избежать / избежать ошибки сборки мусора, приводящей к чрезмерному сохранению NSClipViewBackingLayer - PullRequest
3 голосов
/ 05 июня 2011

Проблема:

Предполагаемый сбой в сборщике мусора.

Вопрос:

Как вы справляетесь с этим?

Могу ли я что-нибудь ещекроме подачи сообщения об ошибке?Очевидным решением было бы: «не изменяйте размер представления», но это слишком повредило бы функциональности.Было бы полезно предотвратить перерисовку представлений до завершения изменения размера?Я попытался [… 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, размер которых изменяется.Почему я подозреваю это?

  1. Укрощение IKImageView было королевской PITA от начала до конца (недостаточно документировано, содержит ошибки, множество функций, но нет доступа к ним).

  2. Сбой происходит во время изменения размера NSScrollView с 3 IKImageViews.

  3. Основной поток останавливается при [IKImageView zoomImageToFit:]


Обновление в ответ на @bbum и @Peter Hosey

Мне не удалось исправить, но в основном обойти сбой сборщика мусора.

  1. Включено: MallocStackLoggingNoCompact AUTO_REFERENCE_COUNT_LOGGING
  2. перерыв в auto_zone_resurrection_error
  3. получить адрес избыточного блока (в данном случае 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 ]

1 Ответ

2 голосов
/ 05 июня 2011

Сначала подайте ошибку. Это скорее всего ошибка в IKImageView. Тьфу.

Далее, включите ведение журнала в стеке malloc (см. man malloc), а также установите AUTO_REFERENCE_COUNT_LOGGING в YES, вы можете использовать malloc_history (или info malloc) в GDB, чтобы точно определить, где был сохранен объект.

<Ч />

Звучит как ошибка в IK и CoreAnimation; пожалуйста, подайте это. А именно, если во время изменения размера возникают незавершенные анимации, то, по сути, это транзакции в полете. Когда сборщик видит, что объект является мусором, CA по совпадению создает новую сильную ссылку через CFRetain (), пока объект завершается.

Теоретически, вы должны иметь возможность хранить сильную ссылку - CFRetain или помещать ее в глобальный массив или что-то в этом роде - чтобы объект не был собран. Затем, как только объект был удален из дерева рендеринга и все анимации действительно сделаны, вы можете удалить сильную ссылку на объект, и он исчезнет без жалоб [надеюсь, что все еще может быть ошибка, которая вызовет проблему даже с этим].

И, действительно, пожалуйста, сообщите об ошибке и укажите на этот ТАК вопрос в вашей ошибке. Этого не должно быть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...