objective-c - 了解 malloc_history 转储

标签 objective-c ios malloc-history

如果您曾经问​​过我如何调试 objective-c 中的释放/分配问题,您会遇到这些有助于追踪问题的环境设置:

  • NSZombieEnabled - 在发布后保留 abjects,因此您可以获得指示等。
  • MallocStackLogging - 保留对象历史记录供以后引用
  • NSDebugEnabled

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


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

MyApp [4413:40b] -[CALayer retainCount]: message sent to deallocated instance 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 那么为什么错误表明它已被释放(net +1 alloc)?

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


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

用仪器进行僵尸检测:

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

查看 Zombie 的回溯,看起来保留计数正在被调用:通过 release_root_if_unused 的 Quartz


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

最佳答案

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

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

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

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

如果不是,则可以设置一个断点,以便在收到僵尸消息时中断。设置该断点并查看您在何处停止。


好的——所以,CoreAnimation 将保留计数用于内部用途(系统框架可以逃脱这一点,尽管它很脆弱)。

我认为 -1 是一个转移注意力的东西;僵尸很可能返回 0xFF....FFFF 作为保留计数,这在 Instruments 中呈现为 -1。

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

您尝试过“构建和分析”吗?偶尔它可能会发现某个地方的 View 管理不善。

在任何情况下,作为实验,请尝试多保留您的 View 一段时间,看看是否可以解决此问题。如果确实如此,那至少是一条线索。

(或者可能是系统框架的bug……也许……但值得怀疑。)

最后,到底是谁在调用 retainCount?!?!? 在 CoreAnimation 的情况下,retainCount 可能是在内部用作实现细节。

不过,如果这是您的代码,那么僵尸调用的位置应该非常明显。

关于objective-c - 了解 malloc_history 转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4366226/

相关文章:

iphone - Xcode错误语义错误值可能无法响应 'initWithFrame:image Name:'

iphone - 用于将应用程序与外部硬件配对的通配符应用程序 ID

iphone - 使用 block 枚举 NSArray 以查找和存储数组中所有 NSString 的所有索引

ios - 如何使用 NSBundle 从指定的路径或文档目录获取图像

ios - 在 ios swift 的新表格 View 中添加表格 View 的收藏项

iPhone - 调试 "pointer being freed was not allocated"错误

objective-c - 如何在 Interface Builder 中使用数学符号

objective-c - Objective C 中的条件语句到底是什么?