跟踪所有Objective-C的alloc/allocWithZone/dealloc

Unc*_*MiF 1 memory cocoa memory-leaks objective-c objective-c++

很抱歉有很长的描述,但问题并不那么容易......

我的项目没有GC编写.最近我发现了一个我无法找到的内存泄漏.我没有使用新的Xcode Analyzer.我确实逐行阅读了我的代码并验证了所有的alloc/release/copy/autorelease/mutableCopy/retain和pool ... - 仍然没有.

序言:标准仪器和全方位泄漏检查不通过某种原因,我的工作(10min为单位工具拒绝我的应用程序,Instruments.app(泄漏)吃了太多的内存和CPU,所以我就没有机会使用它).

因此,我想编写并使用我自己的代码来挂钩和跟踪"所有"alloc/allocWithZone:/ dealloc消息统计信息,以编写一些简单的自己的泄漏检查库(主要目标只是标记具有可能泄漏的对象的类名).

我使用的主要挂钩技术:

  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");
    }
   }
  }
Run Code Online (Sandbox Code Playgroud)
  • 像这样的代码用于挂接alloc方法,而dealloc用作NSObject类别方法.

我保存IMP用于以前的方法实现,然后注册并计算所有alloc/allocWithZone:调用为increment(+ 1)stat-array NSInteger值,dealloc调用为减量(-1).

作为终点,我调用前面的实现并返回值.

在概念上一切正常.

如果需要,我甚至可以检测类何时是类集群的一部分(如NSString,NSPathStore2; NSDate,__ NSCFDate)......通过一些规范化函数(但对于下面描述的问题无关紧要).

但是这种技术存在一些问题:

  • 并非所有类都可以被捕获,例如,[NSDate date]没有捕获alloc/allocWithZone:但是,我可以在GDB中看到alloc调用
  • 由于我正在尝试使用自动单例检测技术(基于retainCount readind)从最终统计信息中自动排除某些对象,因此在启动完整Cocoa应用程序时,NSLocale创建会在pre-init阶段冻结(实际上,即使是简单的Objective-C命令行也是如此)包含Foundation框架的实用程序在main()之前有一些额外的初始化 - 由GDB有allocWithZone:一个接一个地调用,....

完整概念 - 项目草案来源上传到这里:http://unclemif.com/external/DILeak.zip(3.5 Kb)

Terminal.app运行make来编译它,运行./concept以显示它的运行情况.


一个问题:为什么我不能通过挂钩alloc和allocWithZone:方法来捕获所有对象分配?

第二个问题:为什么迷上allocWithZone:在CFGetRetainCount(或[研究所retainCount])冻结了一些类...

bbu*_*bum 6

圣洁重新发明轮子,蝙蝠侠!

你正在以这种方式努力.完全没有必要推出自己的对象跟踪工具(虽然这是一个有趣的心理练习).

因为您正在使用GC,所以用于跟踪分配和识别泄漏的工具都非常成熟.

在GC下,泄漏将采取两种形式之一; 要么是对很久以前被摧毁的物体有强烈的引用,要么对象CFRetain没有平衡CFRelease.

收藏家非常擅长弄清楚为什么任何给定的物体仍然不受欢迎.

因此,您需要找到一些长时间粘附的对象.任何对象都可以.获得所述对象的地址后,您可以使用"仪器"中的"对象图形"仪器来确定其粘附的原因; 找出仍在提及它或保留的地方.

或者,从gdb,用于info gc-roots 0xaddr查找生根对象的所有各种事物.如果打开malloc历史记录(请参阅malloc手册页),则可以获取保存引用的对象的分配历史记录.


哦,没有GC,呵呵......

您仍然需要大量工具,无需重新发明轮子.

leaks命令行工具会经常给你一些有用的线索.打开MallocStackLoggingNoCompact以使用malloc_history(另一个命令行工具).

或者使用ObjectAlloc工具.

无论如何,您需要识别一个或两个泄漏的对象.有了它,你可以弄清楚它上面挂着什么.在非GC中,这完全是一个弄清楚为什么存在保留不能通过发布平衡的情况.