一、背景
上一篇咱们知道怎么经过xcode东西去探测出野指针问题,可是面对两个严重弊端
- 测验同学无法直接使用
- 人工debug测验,关于一些开释后再次使用的目标来说测验周期短仍是无法获取
针对以上两个痛点,咱们需要开发一款东西,嵌入咱们的工程使随时随地能够进行野指针case扑获
二、检测原理
- 当目标调用dealloc时,仅免除目标的引用关系,然后将该目标变为僵尸目标,一起添加NSProxy协议用于接受音讯进行音讯转发打印反常信息
- 经过链表管理僵尸目标,目标包含指针p,原目标以及加入时刻。
- 当僵尸目标在30秒以内被再次访问时,就会经过NSProxy转发原目标,调用办法,以及仓库信息,抛给业务层,由业务层自行处理。
- 守时扫描僵尸目标,存留超过30秒的僵尸目标,将被清理,收回内存。
三、目标
- 阻拦野指针防止crash
- 阻拦野指针对战进行上报
四、计划评价
本篇计划:
这篇文章选用阻拦dealloc构造zombie目标进行音讯转发获取给已开释目标发音讯的仓库
原因
不管是使用hook c层的free办法仍是上层oc目标的dealloc办法,实践底层都是特别耗费功能的,两者比较hook c层的free办法,覆盖面表广,耗费功能也多,所以综合咱们的实践情况挑选后者
五、详细完成
中心首要流程
外部使用东西
引入pod库
pod 'HuntingZombiesTool'
初始化配置
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//当检测到野指针后的回调,由业务自行处理。可挑选上报错误,也能够直接crash
ZombieConfig.share.throwInfo = ^(NSString * _Nonnull info) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:info userInfo:nil];
};
//司机侧示例代码
ZombieConfig.share.throwInfo = ^(NSString * _Nonnull info) {
NSLog(info);
//能够上报到自己分析渠道
};
ZombieConfig.share.zombieActivityTime = 30;
ZombieConfig.share.classes = [self ownClassesInfo];//如果这儿传空,默认是扫描所有类
[ZombieConfig.share startZombie];
return YES;
}
//获取本项目非系统库的类
- (NSArray <Class>*)ownClassesInfo {
NSMutableArray *resultArray = [NSMutableArray array];
unsigned int classCount;
const char **classes;
Dl_info info;
dladdr(&_mh_execute_header, &info);
classes = objc_copyClassNamesForImage(info.dli_fname, &classCount);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_apply(classCount, dispatch_get_global_queue(0, 0), ^(size_t iteration) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSString *className = [NSString stringWithCString:classes[iteration] encoding:NSUTF8StringEncoding];
Class class = NSClassFromString(className);
[resultArray addObject:class];
dispatch_semaphore_signal(semaphore);
});
return resultArray.mutableCopy;
}
测验类
# 该类设置mrc
- (void)tmpBtnClickd:(UIButton *)sender {
UIView* testObj = [[UIView alloc] init];
[testObj release];
[testObj setNeedsLayout];
}
效果
六、依靠信息
到这儿就完毕了,感谢您的阅览,欢迎阅览我的其他文章!