objective-c - 如何避免/避免导致过度保留NSClipViewBackingLayer的垃圾收集错误

标签 objective-c cocoa garbage-collection

问题:
垃圾回收器可能发生故障。
问题:
你怎么处理这个?
除了提交错误报告,我还能做什么吗?
一个显而易见的解决方案是:“不要调整视图的大小”,但这会对功能造成太大的伤害。
在调整大小之前,防止视图被重绘是否有用?
我试过[…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/

相关文章:

objective-c - iOS应用分发和部署目标

iphone - SKPSMTP消息设置WatchdogTimer :]: message sent to deallocated instance

macos - Mac 应用程序中的“确定”警报按钮不起作用

cocoa - 通过 NSPipe 或 NSFileHandle 发送 EOF 到 NSTask

ios - FBSDKGraphRequest 使用未声明的标识符

ios - 在 block 中将 self 作为参数不会导致循环引用,但对 self 的外部引用会导致循环引用

iphone - PerformSelector In后台泄漏在设备上

python - Python如何使用numpy数组进行垃圾回收追加和删除?

java - JFrame 对象准备好进行垃圾回收的条件

garbage-collection - 哈希表疑似SBCL垃圾回收Bug