问题:
垃圾回收器可能发生故障。
问题:
你怎么处理这个?
除了提交错误报告,我还能做什么吗?
一个显而易见的解决方案是:“不要调整视图的大小”,但这会对功能造成太大的伤害。
在调整大小之前,防止视图被重绘是否有用?
我试过[…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有关。为什么我会怀疑?
驯服IKimVIEWW一直是一个皇家皮塔从开始到结束(在文件,马车,许多特点,但没有机会访问它们)。
在使用3个ikimageviews调整nsscrollview的大小时发生崩溃。
主线程在[ikimageview zoomimagetofit:]处暂停
更新以响应@bbum和@peter hosey
我没能修好,但基本上避开了撞坏的垃圾收集器。
启用:mallocstackloggingnocompact auto_reference_count_logging
再现碰撞
自动恢复区中断错误
获取过保留块的地址(本例中为0x20242cde0,仅供参考)
info malloc 0x20242cde0然后在此地址上产生了大量输出(290 KB纯文本)。最常提到的是:nsview\u recursivedisplayRectiveNeedEdignoringOpacity:isVisibleRect:rectisVisibleRectForView:topView
正如我所料,在绘制nsview时似乎发生了一些事情。
后来我按照“彼得”的建议尝试了乐器。这会产生相当长的已分配对象历史。我需要查看碰撞报告来获取过多的块的地址(而运行的仪器没有控制台的输出,仪器没有立即指出哪一个是违规的块(或者我不知道去哪里看,这完全是可能的))。
# 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
对象没有被过度保留在我的代码中,这使得很难准确地指出哪里出错了。然而,从上文中可以清楚地看出,在核心动画中出现了一些问题。
我已经注意到,当我反复调整窗口大小时,最容易再现崩溃,即使其变大,然后再变大一些。我怀疑崩溃是由第二次调整大小引起的,而nsscrollview中的ikimageviews仍在响应第一次调整大小而设置其内容的动画。
部分“解决方案”:
我已经不是在进行Liveresizing,而是在调整窗口大小后更新ScrollView。
现在,我在每个窗口都进行了大小调整之后,将主窗口的大小设置为1秒。这大大降低了车祸发生的频率,但遗憾的是并没有完全消除。
(ikimageview动画持续时间约为300毫秒,但如果阻止调整大小的持续时间太短,则无效。假设GC在动画完成后激活一段时间。
问:我可以完全禁用ikimageview上的动画吗?
我尝试了未记录的私有方法[someikimageview setanimates:no],但这没有任何效果。
为什么这不能完全消除碰撞?
我想,因为我仍然可以触发调整大小通知,即使我试图阻止窗口大小调整(通过暂时隐藏大小调整字形和修复最大/最小大小)。
问:有没有更好的方法来防止窗口调整大小?
(我读过这个博客:vgable.com/blog/2008/04/11/nswindow-setresizable)
[ps 1:info gc roots 0x20242cde0将挂起(我等待了10分钟;没有输出;从未返回提示)。]
[注2:这也很有用(@bbum's site)using-malloc-to-debug-memory-misuse-in-cocoa]
最佳答案
首先,提交一个bug。这很可能是ikimageview中的一个bug。讨厌。
接下来,打开malloc堆栈日志记录(请参见man malloc
)并将AUTO_REFERENCE_COUNT_LOGGING
设置为YES
,您可以在gdb中使用malloc_history
(或info malloc
)查看对象的确切保留位置。
听起来像是ik和coreanimation中的一个bug;请归档。也就是说,如果在调整大小的过程中出现了未完成的动画,那么——实际上——有事务在运行。当收集器看到对象是垃圾时,CA巧合地通过CfFrices()创建一个新的强引用,同时对象正在被终结。
理论上,您应该能够保存一个强引用(cfretain或将其粘贴到全局数组或其他东西中),以防止对象被收集。然后,一旦对象从渲染树中移除,并且所有动画都真正完成,就可以移除对象的强引用,它将毫无怨言地消失(希望——即使这样,仍然可能有一个bug会导致问题)。
而且,真的,请提交一个bug,并在bug中指向这个so问题。这不应该发生。
关于objective-c - 如何避免/避免导致过度保留NSClipViewBackingLayer的垃圾收集错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6239847/