很抱歉有很长的描述,但问题并不那么容易......
我的项目没有使用GC编写。最近我发现了一个我无法找到的内存泄漏。我没有使用新的Xcode Analyzer。我确实逐行阅读了我的代码并验证了所有的alloc / release / copy / autorelease / mutableCopy / retain和pool ... - 仍然没有。
序言:标准仪器和Omni泄漏检查器由于某种原因不适合我(Omin Tool拒绝我的应用程序,Instruments.app(Leaks)吃太多内存和CPU因此我没有机会使用它。)< / p>
所以我想编写并使用我自己的代码来钩住&amp;跟踪“all”alloc / allocWithZone:/ dealloc messages statistics编写一些简单的自己的泄漏检查库(主要目标只是标记对象的类名和可能的泄漏)。
我使用的主要挂钩技术:
Method originalAllocWithZone = class_getClassMethod([NSObject class],@selector(allocWithZone:));
if (originalAllocWithZone)
{
imp_azo = (t_impAZOriginal)method_getImplementation(originalAllocWithZone);
if (imp_azo)
{
Method hookedAllocWithZone = class_getClassMethod([NSObject class],@selector(hookedAllocWithZone:));
if (hookedAllocWithZone)
{
method_setImplementation(originalAllocWithZone,method_getImplementation(hookedAllocWithZone));
fprintf(stderr,"Leaks Hook: allocWithZone: ; Installed\n");
}
}
}
我为以前的方法实现保存IMP然后注册&amp;计算所有alloc / allocWithZone:调用increment(+1)stat-array NSInteger值,dealloc调用as decrement(-1)。
作为终点,我调用前一个实现并返回值。
在概念上一切正常。
如果需要,我甚至可以检测类何时是类集群的一部分(如NSString,NSPathStore2; NSDate,__ NSCFDate)......通过一些normalize-function(但对于下面描述的问题无关紧要)。
然而,这种技术存在一些问题:
完整概念 - 项目草案来源在此处上传:http://unclemif.com/external/DILeak.zip(3.5 Kb)
从 Terminal.app 运行 make 进行编译,运行 ./ concept 以显示其效果。
第一个问题:为什么我无法通过挂钩alloc&amp;来捕获所有对象分配allocWithZone:方法?
第二个问题:为什么挂钩allocWithZone:在某些类的CFGetRetainCount(或[inst retainCount])中冻结......
答案 0 :(得分:6)
神圣重新发明了轮子,蝙蝠侠!
你正在以这种方式努力。完全没有必要推出自己的对象跟踪工具(尽管这是一项有趣的心理练习)。
因为您正在使用GC,所以用于跟踪分配和识别泄漏的工具都非常成熟。
在GC下,泄漏将采取两种形式之一;要么强烈引用该对象应该很久以前被销毁或该对象已CFRetain
'而没有平衡CFRelease
。
收藏家非常擅长弄清楚为什么任何特定物品都不受欢迎。
因此,您需要找到一些粘贴太久的对象。任何对象都可以。获得所述对象的地址后,您可以使用“仪器”中的“对象图形”仪器来确定其粘附的原因;找出仍在提及它或保留它的地方。
或者,从gdb中,使用info gc-roots 0xaddr
查找生成对象的所有各种事物。如果打开malloc历史记录(请参阅malloc手册页),则可以获取保存引用的对象的分配历史记录。
哦,没有GC,呵呵......
你仍然需要大量工具,无需重新发明轮子。
leaks
命令行工具通常会为您提供一些好的线索。打开MallocStackLoggingNoCompact以使用malloc_history(另一个命令行工具)。
或使用ObjectAlloc工具。
在任何情况下,您都需要识别一个或两个被泄露的对象。有了它,你可以弄清楚它上面挂着什么。在非GC中,这完全是一个弄清楚为什么保留不能通过发布平衡的情况。
答案 1 :(得分:4)
即使没有泄漏仪器,仪器仍然可以帮助您。
从Leaks模板开始,然后从中删除Leaks仪器(因为你说它使用了太多的内存)。单独的ObjectAlloc将告诉您所有对象的分配和释放,以及(在Leaks模板中默认情况下启用了一个选项)所有的保留和释放。
您可以将ObjectAlloc工具设置为仅显示仍然存在的对象;如果你把应用程序带到没有对象(或者某个类没有对象)的地方,并且这些对象仍然存在,那么你就有了泄漏。然后,您可以深入查找泄漏原因。
答案 2 :(得分:-2)
从Xcode模板开始。在你知道自己在做什么之前,不要尝试为可可应用程序推送自己的main()例程。