主页 FB内存检测工具分享
Post
Cancel

FB内存检测工具分享

前言

本文具有强烈的个人感情色彩,如有观看不适,请尽快关闭. 本文仅作为个人学习记录使用,也欢迎在许可协议范围内转载或分享,请尊重版权并且保留原文链接,谢谢您的理解合作. 如果您觉得本站对您能有帮助,您可以使用RSS方式订阅本站,感谢支持!.

讨论

如果申请一大块内存没有被release这属于内存泄漏,并不属于内存竞争导致的持有,根本原因是没有正确的release. 在常规流程下(正常 alloc,release或者 malloc free,亦或是 new delete)合理使用内存,造成内存泄漏的最主要原因是资源的竞争造成的相互持有.这是诱因导致 资源没有被正常释放. 此工具擅长解决 相互持有关系不释放内存问题,精确到实例类型和内存地址,并直观看到 找到相关对象.

内存检测工具-介绍

  • FBMemoryProfiler

    FBMemoryProfiler 是几个组件的结合。其中包括 FBAllocationTracker 和 FBRetainCycleDetector。 可视化工具,直接嵌入到 App 中,可以起到在 App 中直接查看内存使用情况,并筛选潜在泄漏对象的作用

  • FBAllocationTracker

    主要用于快速检测潜在的内存泄漏对象,并提供给 FBRetainCycleDetector 进行检测 这是一个用来主动追踪所有 NSObject 的子类的内存分配和释放操作的工具。

FBAllocationTracker 用于检测应用在运行时所有实例的分配。它的原理其实就是用 method swizzling 替换原本的 alloc 方法。这样就可以记录下所有的实例分配了。

在需要的时候调用 currentAllocationSummary 方法,就可以得到当前整体的实例分配情况(前提是在 main 中初始化过,下面有介绍):

objc NSArray<FBAllocationTrackerSummary *> *summaries = [[FBAllocationTrackerManager sharedManager] currentAllocationSummary];
  • FBRetainCycleDetector

    FBRetainCycleDetector 接受一个运行时的实例,然后从这个实例开始遍历它所有的属性,逐级递归。 如果发现遍历到重复的实例,就说明存在循环引用,并给出报告。

1
2
3
4
5
  FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
 [detector addCandidate:myObject];
 NSSet *retainCycles = [detector findRetainCycles];
 NSLog(@"%@", retainCycles);

代码检测循环引用-原理

在运行时中检测对象 的内存布局,实例地址

1
2
const char *class_getIvarLayout(Class cls);
const char *class_getWeakIvarLayout(Class cls);

support for Objective-C++

代码中使用

1
2
3
4
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:nil];
[detector addCandiate:myObject];
NSSet<NSArray<FBObjectiveCGraphElement *> *> *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);

这里的 myObject ,就是我们所怀疑的实例变量

FBObjectiveCGraphElement 是所有用来查找对象类型的基类。所有的查找对象都基于它实现。该类并不需要外部的调用,主要是供内部查询使用。其提供的功能主要是:

  • 提供初始化方法封装object(即调用addCandiate传入的object
  • 获取所有该对象所持有对象- (NSSet *)allRetainedObjects;。 基类FBObjectiveCGraphElement所获取的对象类型是通过associated object所持有的对象。 associated object对象的获取是通过Facebook自身的fishhookhook原先的objc_setAssociatedObjectobjc_removeAssociatedObjects来实现对象的持有标记。
  • 提供过滤接口- (NSSet *)filterObjects:(nullable NSArray *)objects;,过滤接口主要是与FBObjectGraphConfiguration相结合使用,FBObjectGraphConfiguration会在下文介绍。

FBObjectGraphConfiguration 是提供过滤相关白名单的类,相关的配置

其余的不就在这里过多介绍了.

findRetainCycles查询方式 - DFS深度优先

这里查找对象的方式用的是深度优先遍历搜索

如何使用

示例场景分析

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
@property (nonatomic, strong) NSTimer *timer;
@property(copy,nonatomic)NSString *name;

 self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                              target:self
                                            selector:@selector(handleTimer)
                                            userInfo:nil
                                             repeats:YES];

- (void)handleTimer
{
     self.name = @"123";
}

参考

FBRetainCycleDetector分析
automatic-memory-leak-detection-on-ios

该博客文章由作者通过 CC BY 4.0 进行授权。

iOS开发中的字符串枚举

NS-OPTIONS的用法