代码内存泄露检测(1) MLeaksFinder (Wechat开源) + FBRetainCycleDetector (FaceBook开源)
每次项目编译完成之后,都被内存搞得头昏脑胀,压力甚大。
利用两周时间,稍微研究了 微信开源的 MLeaksFinder 和 facebook 开源的 FBMemoryProfiler,
这两个开源三方,在编写过程中就可以检测内存泄露,实在是不要太方便……
希望自己在下一个项目能用的得心应手……
- 微信 MLeaksFiner
如果对它,你还是不是很了解 ,可以到查阅这里: http://wereadteam.github.io/2016/07/20/MLeaksFinder2/ ;
1.1 创建demo 项目 LeakDemo 引入 MLeaksFiner 开源文件夹
->本次 我是直接下载到本地了,所以直接拖拽到了项目
image1.2 引入这个开源文件后 ,不用写多余的代码,默认debug 编译的时候,自动启动使用
下面来写一段内存泄露的代码,进行试验::
内存泄露的代码::
在 main.storybord 中添加 NavigationController
imageVC 代码 ViewController .m ::
#import "ViewController.h"
#import "FirstController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"vc";
[self creatButton];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)creatButton{
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
[self.view addSubview:button];
button.center = self.view.center;
[button setTitle:@"下一页" forState:UIControlStateNormal];
button.backgroundColor = [UIColor yellowColor];
[button addTarget:self action:@selector(didButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)didButtonClick:(UIButton*)btn{
NSLog(@"vc btn Click");
[self.navigationController pushViewController:[FirstController new] animated:true];
}
新建 FirstController :
#import "FirstController.h"
#import "TestView.h"
@interface FirstController ()
@property (nonatomic,strong)TestView *testView;
@end
@implementation FirstController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"first vc";
self.view.backgroundColor = [UIColor whiteColor];
[self addTestView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)addTestView{
self.testView = [[TestView alloc]initWithFrame:CGRectMake(0, 0, 200, 30)];
self.testView.vc = self;
[self.view addSubview:self.testView];
self.testView.center = self.view.center;
}@end
新建 TestView :
TestView .h
#import <UIKit/UIKit.h>
#import "FirstController.h"
@interface TestView : UIView
@property (nonatomic,strong)FirstController *vc;// 把这个属性 换成 strong 属性 故意造成 泄露
@end
TestView .m
#import "TestView.h"
@implementation TestView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self prepareUI];
}
return self;
}
-(void)prepareUI{
self.backgroundColor = [UIColor redColor];
}
@end
内存泄露的解释::::
vc -> push -> first VC
:( first vc 强持有 testView ,testView 强持有 firstVc : 彼此强持有,无法释放)
-> pop 回-> vc
=》: first vc 无法释放
1.3 检测 到泄露 alert 方式体提醒 :::
image这里检测到是有 循环泄露的,但是无法准确定位泄露的对象
所以继续……
2 . MLeakFinder + FBRetainCycleDetector
2.1 查阅了 MLeaksFinder.h 的文件
image这段宏定义的解释 https://www.jianshu.com/p/e3dbf58982f6:::
#ifdef MEMORY_LEAKS_FINDER_ENABLED
//_INTERNAL_MLF_ENABLED 宏用来控制 MLLeaksFinder库
//什么时候开启检测,可以自定义这个时机,默认则是在DEBUG模式下会启动,RELEASE模式下不启动
//它是通过预编译来实现的
#define _INTERNAL_MLF_ENABLED MEMORY_LEAKS_FINDER_ENABLED
#else
#define _INTERNAL_MLF_ENABLED DEBUG
#endif
//_INTERNAL_MLF_RC_ENABLED 宏用来控制 是否开启循环引用的检测
#ifdef MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
#define _INTERNAL_MLF_RC_ENABLED MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
//COCOAPODS 因为MLLeaksFinder引用了第三库用来检查循环引用,所以必须是当前项目中使用了COCOAP
//ODS,才能使用这个功能。
#elif COCOAPODS
#define _INTERNAL_MLF_RC_ENABLED COCOAPODS
#endif
2.2 . 添加cocopod ,然后 Pod 添加 FBRetainCycleDetector;
注释 这两段代码 == 》同时开启 MLeakfinder 检测 和 retainCycle 检测
//#define MEMORY_LEAKS_FINDER_ENABLED 0
#ifdef MEMORY_LEAKS_FINDER_ENABLED
#define _INTERNAL_MLF_ENABLED MEMORY_LEAKS_FINDER_ENABLED
#else
#define _INTERNAL_MLF_ENABLED DEBUG
#endif
//#define MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED 0
#ifdef MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
#define _INTERNAL_MLF_RC_ENABLED MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
#elif COCOAPODS
#define _INTERNAL_MLF_RC_ENABLED COCOAPODS
#endif
重新编译运行 弹框是这样
image image正确找到 循环引用 cycle
最简单的使用方法了吧,先使用着,有机会会研究下 源码 ^ V ^
网友评论