infer是Facebook 的 Infer 是一个静态分析工具。可以分析 Objective-C, Java 或者 C 代码,报告潜在的问题。

  任何人都可以使用 infer 检测应用,可以将严重的 bug 扼杀在发布之前,同时防止应用崩溃和性能低下。

  iOS开发之使用 infer静态代码扫描工具-风君雪科技博客

  infer 可以检查 Java 和 Android 中的 NullPointException 和资源泄漏。

  除了以上,infer 还可以检测 iOS 和 C 代码的内存泄漏!

  应用范围:

    包括 Facebook Android 和 iOS 主客户端,Facebook Messenger, Instagram 在内的,以及其他影响亿万用户的手机应用,每次代码变更,都要经过 Infer 的检测。 

  infer 优点:

    1、效率高、规模大,几分钟能扫描上千行代码;

    2、支持增量及非增量分析;

    3、分解分析,输出整合结果(infer能将代码分解,小范围分析后再将结果整合在一起,兼顾分 析的深度和速度) ;

  在 iOS 和 C 中,infer 能捕捉的 bug 类型有:

    1、资源泄漏;

    2、内存泄漏;

    3、null 引用;

    4、Premature nil termination argument 

  只在 OC 中捕捉的 bug 类型有:

    1、循环引用(Retain cycle);

    2、参数非空检查;

    3、实例变量非空检查;

  Github 地址:https://github.com/facebook/infer

  配置 infer 安装:

    1、homebrew 安装:

    brew install infer

    如果安装报错,可根据提示信息更新 brew:brew update

    2、在官网下载安装包进行安装:  

    安装成功之后,输入 infer –version 来查看版本号:

    iOS开发之使用 infer静态代码扫描工具-风君雪科技博客

  配置到环境变量: 

    echo "export PATH="$PATH:pwd/infer/infer/bin"" >> ~/.bash_profile &&source ~/.bash_profile

  

  使用 infer 工具进行代码分析:

  分析单个文件:

  分析工程:

    infer run — xcodebuild -target <target name> -configuration <build configuration> -sdk iphonesimulator

  如果是 Pod 工程,执行:

    infer run — xcodebuild -workspace AVRecorder.xcworkspace -scheme AVRecorder -configuration Debug -sdk iphonesimulator

  ps:被这个 infer run 命令给坑了,按照其他人博客上的命令:infer — xcodebuild -target HelloWorldApp -configuration Debug -sdk iphonesimulator 

   出现错误:

** BUILD FAILED **

Internal Error:   /usr/local/Cellar/infer/0.15.0/lib/infer/infer/bin/../lib/python/infer.py
  -j 8 --project-root
  /Users/zhangtibin/Downloads/infer-master/examples/ios_hello --out
  /Users/zhangtibin/Downloads/infer-master/examples/ios_hello/infer-out --
  xcodebuild -project HelloWorldApp.xcodeproj -scheme HelloWorldApp
  -configuration Debug:
  exited with code 65
Error backtrace:
Raised at file "base/Die.ml" (inlined), line 25, characters 6-36
Called from file "base/Logging.ml", line 314, characters 58-80
Called from file "integration/Driver.ml", line 159, characters 2-16
Called from file "integration/Driver.ml", line 280, characters 6-420
Called from file "infer.ml", line 20, characters 2-36
Called from file "infer.ml", line 130, characters 8-54

  改成命令:infer run — xcodebuild -target <target name> -configuration <build configuration> -sdk iphonesimulator 后解决。

  iOS开发之使用 infer静态代码扫描工具-风君雪科技博客

  其他用法命令可参考:https://fbinfer.com/docs/analyzing-apps-or-projects.html

  如果出现:Nothing to compile. Try cleaning the build first.

  可使用:xcodebuild -target HelloWorldApp -configuration Debug -sdk iphonesimulator clean,保证增量到非增量转换。

  iOS开发之使用 infer静态代码扫描工具-风君雪科技博客

  添加静态分析工具忽略文件:

   在工程目录下新建 .inferconfig 文件, 内容如图, 可以过滤掉Pods文件夹下的第三方库, skip-analysis-in-path是一个数组, 想要过滤其他文件, 只需要增加路径即可

  iOS开发之使用 infer静态代码扫描工具-风君雪科技博客

  出现常见错误类型有:

    1、NULL_DEREFERENCE:空指针的情况。

    1.传参为0的情况下。例如代码中,在调用showAlertViewA()时,将tag传参为0,infer检测此处传0,判断为一个NULL空指针,所以爆出警告。这里可以理解为误报,不会出现问题。

    2.通过malloc,calloc,realloc等函数申请内存,当内存不足时,有可能会在该函数中返回NULL,如果没有做NULL的判断,则警告

    3.在创建NSArray或者NSDictionary时,传入的参数有可能会nil。由于NSArray与NSDictionary不接受空指针,所以在对其addObject或者setObject:forKey: 时需要进行判断一下是否为nil

    2、MEMORY_LEAK:内存泄漏:
     项目代码全面启动了ARC进行内存管理,在OC层没有扫描出内存泄露。目前扫描出的内存泄露问题都是使用了malloc或者ralloc等c语言内存申请函数,在函数提前return前没有及时free

    3、RESOURCE_LEAK:资源泄漏
    4、ASSIGN_POINTER_WARNING

      由于在mrc时代,没有weak指针,所以一些view的属性声明是_、unsafe__unretain__的形式,在arc中,这个属性被判断为assign,需要将其修改为weak或者strong
    5、DIRECT_ATOMIC_PROPERTY_ACCESS

      在代码中使用了使用了一个atomic的成员变量,infer建议我们将atomic修改为nonatomic。由于OC中,属性会被默认设置为atomic属性,我们需要显示将属性声明为nonatomic。

    6、IVAR_NOT_NULL_CHECKED    

      在代码中调用block,运行代码时,没有做判空处理。即需要改动为,if(block){block()}

    7、BAD_POINTER_COMPARISON

      没有判断一个NSNumber类型的对象是不是空?

    8、TAINTED_VALUE_REACHING_SENSITIVE_FUNCTION

      代码中使用了cookie的value。可以理解为误报

    9、PARAMETER_NOT_NULL_CHECKED

      传参时没有判断是否为null,加一次判断就可以了

    10、STRONG_DELEGATE_WARNING

      将一个delegate属性设置为strong的类型。

    11、PREMATURE_NIL_TERMINATION_ARGUMENT

      没有判断是否为空

    12、REGISTERED_OBSERVER_BEING_DEALLOCATED

      创建一个对象后,监听了某些通知,但是没有在dealloc中释放该通知。项目中出现这种问题的类,基本都是单例,不会被销毁。