安装
brew install infer && infer --version
brew install sqlite && STATIC_DEPS=true sudo pip3 install lxml
使用
- 分析并输出结果
对于大型项目可能出错,建议先输出编译日志再进行分析
-
分析xcodeproj项目:
$infer -- xcodebuild -project 项目名.xcodeproj -scheme 项目名 -configuration Release -sdk iphoneos -
分析workspace项目:
$infer -- xcodebuild -workspace 项目名.xcworkspace -scheme 项目名 -configuration Release -sdk iphoneos -
分析iOS文件:
$infer -- clang -c -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk *.m -
分析c文件:
$infer -- clang -c ac.m
- 分析并输出json文件
-
输出编译日志
xcodebuild -project 项目名.xcodeproj -scheme 项目名 -configuration Release -sdk iphoneos COMPILER_INDEX_STORE_ENABLE=NO OTHER_CFLAGS="-DNS_FORMAT_ARGUMENT(A)= -D_Nullable_result=_Nullable" | tee xcodebuild.log -
格式化编译日志
xcpretty -r json-compilation-database -o compile_commands.json < xcodebuild.log > /dev/null -
输出分析报告
直接输出:
infer run --keep-going --skip-analysis-in-path Pods --compilation-database-escaped compile_commands.jsonxml格式:
infer --pmd-xml --keep-going --skip-analysis-in-path Pods --compilation-database-escaped compile_commands.jsonhtml格式:
infer --html --keep-going --skip-analysis-in-path Pods --compilation-database-escaped compile_commands.json
- 跳过分析指定target
在工程根目录下添加.inferconfig:
{
"skip-analysis-in-path":[
"Pods/AFNetworking",
"Pods/Bugly"
]
}
{
"skip-analysis-in-path":["Pods"]
}
分析出的问题类型:
变量未使用(dead_store)
为空判断
-
空指针异常(Null Dereference):当一个对象声明后,没有初始化,就被引用了,这个时候会报空指针错误。
- 传参为0的情况。例如代码中,在调用showAlertViewA()时,将tag传参为0,infer检测此处传0,判断为一个NULL空指针,所以爆出警告。这里可以理解为误报,不会出现问题。 - 通过malloc,calloc,realloc等函数申请内存,当内存不足时,有可能会在该函数中返回NULL,如果没有做NULL的判断,则警告 - 在创建NSArray或者NSDictionary时,传入的参数有可能会nil。由于NSArray与NSDictionary不接受空指针,所以在对其addObject或者setObject:forKey: 时需要进行判断一下是否为nil -
参数未判空(parameter_not_null_checked): 例如block未判空就进行调用。
-
本地变量不为空的检查(Ivar not null checked)
方法调用
- 调用可选方法前未做实现判断(unsafe_call_to_optional_method):例如直接调用[error debugDescription],debugDescription不一定实现导致崩溃。
循环引用
-
循环引用(Retain cycle):内存死锁只存在OC中,A 创造B,B也创造了A,然后你等我,我等你,都无法释放
-
deleate属性为strong(STRONG_DELEGATE_WARNING):
-
指针类型为assign(ASSIGN_POINTER_WARNING):
-
block中使用了强引用self(captured_strong_self):在block中使用了self,如果block被self强引用,会构成循环引用。
-
block中弱引用对象多次出现(multiple_weakself):此种情况下有可能代码执行过程中self被释放,执行流程非闭环,出现脏数据或资源泄漏等问题。
-
内存泄漏 (Memory leak):内存泄漏的问题只在C/OC中报告
-
资源泄漏(RESOURCE_LEAK)
闭环处理
-
nstimer置为无效
-
通知注册后未删除(REGISTERED_OBSERVER_BEING_DEALLOCATED):创建一个对象后,监听了某些通知,但是没有在dealloc中释放该通知。项目中出现这种问题的类,基本都是单例,不会被销毁。
内存泄漏误报的情况:
__bridge:
CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化。
OC->CF:
CGImageSourceRef source = (__bridge CFURLRef)(NSURL * url);
CF->OC:
__bridge_transfer:
常用在CF对象转化成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存,作用同CFBridgingRelease()
id obj = (__bridge_transfer id)p;其中obj为OC类,p为CF指针
__bridge_retained:
与__bridge_transfer 相反,常用在将OC对象转化成CF对象,且OC对象的所有权也交给CF对象来管理,即OC对象转化成CF对象时,涉及到对象类型和对象所有权的转化,作用同CFBridgingRetain()
void *p = (__bridge_retained void *)obj;其中obj为OC类,p为CF指针
QA
- 路径中不能有中文