Luk*_*ice 9 objective-c malloc-history ios
如果您曾经问过如何在objective-c中调试发布/分配问题,您将遇到这些可以帮助跟踪问题的环境设置:
NSZombieEnabled - 发布后保持不变,所以你可以获得指针等.MallocStackLogging - 保留对象历史记录以供日后参考 NSDebugEnabled您可以将所有这些设置YES为"可执行文件"(在组树中找到)信息中"参数"选项卡的"环境"部分.
所以,我得到这个控制台输出
MyApp [ 4413:40b] - [CALayer retainCount]:发送到解除分配的实例0x4dbb170的消息
然后打开终端,而调试器转发了break并输入:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我不明白的是,如果它的历史是ALLOC,FREE,ALLOC那么为什么错误表明它已被释放(net +1 alloc)?
还是我对转储的理解错了?
用仪器进行僵尸检测:

为什么以及如何,保留计数从1跳到-1?
看看Zombie的回溯,看起来像保留计数被调用:Quartz through release_root_if_unused
编辑:已解决 - 我正从超级删除视图,然后释放它.通过释放它来修复.
@Kay是正确的;malloc 历史记录显示指定地址处的两次分配;一个已分配并释放,一个仍在使用。
retainCount您需要的是对CALayer已释放的调用的回溯。因为您启用了僵尸检测,除了其他内存调试之外,释放可能根本没有发生并且不会发生。
将 malloc 历史记录与僵尸检测混合会显着改变运行时行为。
我建议在 Instruments 中运行僵尸检测。希望这能查明确切的问题。
如果没有,那么您可以设置一个断点,以便在向僵尸发送消息时中断。设置断点并查看停在哪里。
好的——所以,CoreAnimation 将保留计数用于内部目的(系统框架可以摆脱这一点,尽管它很脆弱)。
我认为 -1 是转移注意力的;僵尸很可能返回 0xFF....FFFF 作为保留计数,这在 Instruments 中呈现为 -1。
下一个最佳猜测;由于这是在计时器中发生的,因此过度释放可能发生在动画期间。CoreAnimation 层应该正确处理这个问题。代码中存在视图或动画层容器的过度释放,导致该层过早消失。
您尝试过“构建和分析”吗?它偶尔可能会在某个地方发现视图管理不善。
无论如何,作为一个实验,尝试多保留你的观点一段时间,看看这是否能让这个问题停止。如果确实如此,那至少是一条线索。
(或者它可能是系统框架中的一个错误......也许......但值得怀疑。)
最后,到底是谁在打电话retainCount?!?!? 对于 CoreAnimation,它可能retainCount在内部用作实现细节。
不过,如果这是您的代码,那么僵尸调用的位置应该非常明显。
| 归档时间: |
|
| 查看次数: |
6482 次 |
| 最近记录: |