【问题标题】:Understanding a malloc_history dump了解 malloc_history 转储
【发布时间】:2010-12-06 12:08:46
【问题描述】:

如果您曾经问​​过我如何在 Objective-c 中调试 release/alloc 问题,您会遇到这些有助于追踪问题的环境设置:

  • NSZombieEnabled - 发布后保留 abjects,以便您获得指针等。
  • MallocStackLogging - 保留对象历史供以后参考
  • NSDebugEnabled

您在“可执行文件”(可在组树中找到)信息的“参数”选项卡的“环境”部分中将所有这些设置为 YES


所以,我得到了这个控制台输出

MyApp [4413:40b] -[CALayer retainCount]:消息发送到 解除分配的实例 0x4dbb170

然后打开终端,而调试器已转发中断并键入:

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 

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

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

我不明白的是,如果它的历史是 ALLOC、FREE、ALLOC 那么为什么错误表明它已被释放(净 +1 分配)?

还是我对转储的理解有误?


编辑(新运行=不同的对象指针):

使用仪器检测僵尸:

为什么以及如何,保留计数会从 1 跳到 -1?

查看 Zombie 的回溯,看起来保留计数被调用:Quartz through release_root_if_unused


编辑:已解决- 我正在从 super 中删除一个视图,然后将其释放。只需释放它即可修复。

【问题讨论】:

    标签: objective-c ios malloc-history


    【解决方案1】:

    @Kay 是正确的; malloc 历史显示指定地址的两个分配;一个已被分配和释放,一个仍在使用中。

    您需要的是已经发布的CALayer 上对retainCount 的调用的回溯。因为您启用了僵尸检测,除了其他内存调试之外,可能是释放根本没有也不会发生。

    将 malloc 历史记录与僵尸检测相结合会显着改变运行时行为。

    我建议在 Instruments 中运行僵尸检测。希望这能查明确切的问题。

    如果没有,那么有一个断点可以设置为在收到僵尸消息时中断。设置断点,看看你在哪里停止。


    好的——所以,CoreAnimation 将保留计数用于内部目的(系统框架可以解决这个问题,尽管它很脆弱)。

    我认为 -1 是红鲱鱼;僵尸很可能返回 0xFF....FFFF 作为保留计数,这在 Instruments 中呈现为 -1。

    下一个最佳猜测;由于这是在计时器中发生的,因此过度释放可能发生在动画期间。 CoreAnimation 层应该正确处理这个问题。您的代码中存在过度释放的视图或动画层容器,导致该层过早消失。

    您是否尝试过“构建和分析”?偶然它可能会在某个地方发现对视图的管理不善。

    在任何情况下,作为一个实验,试着多保​​留你的观点一段时间,看看这是否能让这个问题停止。如果是这样,那至少是一个线索。

    (或者它可能是系统框架中的一个错误......也许......但值得怀疑。)

    最后,到底是谁在调用 retainCount?!?!? 对于 CoreAnimation,retainCount 可能在内部用作实现细节。 p>

    如果是你的代码,那么僵尸调用的位置应该很明显。

    【讨论】:

    • 感谢您对此的帮助,跟踪问题:我正在从具有子视图和(大)子层的 super 中删除一个视图,然后在此之后释放该视图。相反,现在我只是释放。自从我将应用程序更新到 4.2 (ipad) 后它才开始发生 - 所以吸取了教训。再次感谢。
    【解决方案2】:

    我不是专家,但如果你看一下第 3 块的第一行:

    ALLOC 0x4dbb170-0x4dbb19f [size=48]:

    在其他两个输出中,0x4dbb160-0x4dbb171 处的大小为 18 的内存块被分配和释放。我假设旧对象已被释放,并且此内存地址处有一个新对象。因此,0x...b160 处的旧实例不再有效。

    【讨论】:

    • 我认为尺寸可能是一个指标。对象的 id 是起始地址,因此块 3 中分配的对象是导致我的问题的对象(因为它的起始地址是控制台中报告的对象)。
    • 我不明白的是它在这里清楚地显示它是分配的。但错误表明它已被释放...
    • 你说得对,我希望 malloc 历史上的第 4 个条目表明 b170 是免费的。也许指向内存本身的指针已损坏?您是否在“运行”菜单中启用了“停止 Obj-C 异常”?前段时间我收藏了一个网站loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html。也许你在那里找到了一些提示。
    • EXC_BAD_ACCESS 不是异常,而是崩溃。停止 Obj-C 异常不会停止(但调试器总是会)。
    猜你喜欢
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多