- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
如果您曾经问过我如何调试 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/
如果您曾经问过我如何调试 objective-c 中的释放/分配问题,您会遇到这些有助于追踪问题的环境设置: NSZombieEnabled - 在发布后保留 abjects,因此您可以获得指示等
我将以下环境变量添加到我的项目中并将其值设置为 YES。 NSDebug已启用 NSZombie启用 MallocStack日志记录 MallocStackLoggingNoCompact 我遵循ht
我在自定义 UIView 中使用以下方法时遇到内存问题(是的;)我是 iOS 的新手: 头文件 .... @property (nonatomic, retain) NSString * pre
我是一名优秀的程序员,十分优秀!