news 2026/9/24 15:35:25

Infer 静态分析:`infer run` 命令完全指南(capture + analyze 一体化工作流)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Infer 静态分析:`infer run` 命令完全指南(capture + analyze 一体化工作流)
  • 静态分析
  • 代码质量
  • 开发工具

【免费下载链接】infer

A static analyzer for Java, C, C++, and Objective-C

项目地址:https://gitcode.com/gh_mirrors/infer/infer
点击查看免费下载

infer run是 Facebook 开源静态分析器 Infer 中最常用的一站式命令:它把"抓取源码(capture)"与"运行分析(analyze)"两个阶段串联起来,一条命令完成从编译命令到问题报告的完整链路。本文基于本仓库website/versioned_docs/version-1.3.0/man-infer-run.md对应的手册内容(渲染自 infer-run.1.html,原文位于 infer/man/man1/infer-run.txt),并结合仓库源码逐项解析全部命令行选项的语义与实现原理,帮助你在 Java、C/C++、Objective-C 等项目上正确、高效地使用infer run,并掌握报告过滤、调试排障、Buck 集成等进阶技巧。

一、infer run的本质:capture 与 analyze 的合成命令

infer run并非一个独立实现的分析引擎,而是 Infer 顶层驱动器(driver)对外暴露的复合入口。手册 DESCRIPTION 一节明确给出其等价关系:

infer run [options] 等价于依次执行: infer capture [options] infer analyze [options]

也就是说,infer run先调用 capture 阶段把目标源码翻译成 Infer 的中间表示(SIL),再调用 analyze 阶段对中间表示执行各检查器(checker)的分析。这一点在仓库入口源码中得到印证:在 infer/src/infer.ml#L134-L137 中,Analyze命令走Driver.run Analyze,而Capture | Compile | Run三个命令统一走Driver.run (Lazy.force Driver.mode_from_command_line)——RunCapture共用同一套驱动逻辑,由命令行模式决定是否顺带完成分析。此外 infer/src/infer.ml#L16-L66 的setup ()会在 Run 模式下创建 results 目录并清理旧的 infer-out 结果,保证每次infer run从干净状态开始。

因此,任何可以拆成captureanalyze的用法,都可以合并进一条infer run;同时,由于选项是共享的,本手册中列出的选项同样适用于拆分的两个阶段(对应选项在帮助手册中分别标记在RunCaptureAnalyzeReport命令下)。

二、基本用法与两种调用形式

手册 SYNOPSIS 给出两种等价写法:

infer run [options] infer [options] -- compile command
  • 第一种:直接运行infer run,配合.inferconfig配置文件或在当前目录执行,适用于已配置好的项目。
  • 第二种:infer -- 编译命令是更常见的日常用法,--之后的参数被原样当作构建命令交给 Infer 拦截。例如对 C 项目执行infer run -- gcc -c example.c,对 Java 项目执行infer run -- javac Hello.java

本仓库 examples/c_hello/example.c 与 examples/java_hello/Hello.java 就是可用的最小示例;对应的构建脚本位于 examples/c_hello/Makefile 与 examples/java_hello/Makefile,可从中看到与infer run -- <编译命令>完全一致的调用方式。

默认情况下,分析结果写入当前目录下的infer-out/,其中report.txt(人类可读)与report.json(机器可读)为主要产物;若要改变输出位置,使用--results-dir

三、核心选项详解

以下按功能分组,逐项解析infer run手册中的全部选项。

3.1 抓取(Capture)相关

--capture-block-list jsonMatcher 或 matcher 列表,指定不应被抓取、因此也不会被分析的文件。仅对 Clang、Java、Hack 生效。其底层实现在 infer/src/IR/inferconfig.ml#L287-L288:capture_block_list_file_matcher通过FileOrProcMatcher.load_matchers加载 JSON 模式,构造一个"源文件包含字符串"匹配器;选项本身的声明位于 infer/src/base/Config.ml#L993-L999。匹配器支持两种 JSON 形态:

  • 源文件模式:{"source_contains": "子串"}(可选配not_contains),匹配内容包含指定子串的文件;
  • 方法模式:{"class": "类名", "method": "方法名"},匹配指定类/方法。

该匹配器在三个前端中被实际调用:Clang 前端 infer/src/clang/cLocation.ml#L81、Java 前端 infer/src/java/jMain.ml#L95、Hack 集成 infer/src/integration/Hack.ml#L267,均为"命中 block list 则跳过该文件"的短路逻辑。示例:

--capture-block-list '[{"source_contains": "generated"}]'

3.2 报告过滤与输出格式

--censor-report +string指定"审查(censor)"过滤器:被命中的问题会在 JSON 报告中额外写入一个censored_reason字段;这些被审查的问题不会出现在控制台输出与 report.txt 中,但处理 JSON 报告的下游工具仍可读取。多个过滤器按指定顺序依次作用于每一个被检测到的问题,只有通过所有过滤器的问题才会被报告。

每个过滤器的格式为:

<issue_type_regex>:<filename_regex>:<reason_string>
  • 前两个分量是 OCaml Str 正则表达式,可带可选的!前缀;
  • !前缀时极性反转,过滤器从"允许列表"变为"阻止列表"(block list);
  • 每个过滤器按蕴含(implication)解释:一个问题若不匹配issue_type_regex,或匹配filename_regex,则该问题命中此过滤器;
  • 参与匹配的文件名是相对于--project-root目录的路径;
  • <reason_string>是非空字符串,用于说明该问题被过滤的原因。

例如--censor-report 'NULLPTR_DEREFERENCE:.*tests.*:known fp in tests'表示把 tests 目录下的空指针解引用问题标记为已知误报(fp)。

--no-censor-report +issue_type_regex仅供调试/实验使用:指定--censor-report审查的问题类型正则。

--report-allow-list-path-regex +path_regex只报告"相对路径匹配指定 OCaml 正则"(且不匹配--report-block-list-path-regex)的文件上的问题。

--report-block-list-path-regex +path_regex不报告相对路径匹配该正则的文件上的问题,即使它们命中了上面的 allow list。

--report-block-list-files-containing +string不报告"内容包含指定字符串"的文件上的任何问题。

--report-block-list-spec json按规格(spec)列表屏蔽特定问题。手册给出完整示例格式:

[ { "bug_type": "CXX_REF_CAPTURED_IN_BLOCK", "procedure_name": "foo", "file": "path/to/File.m", "comment": "This is a fp because..." }, { "bug_type": "RETAIN_CYCLE", "class_name": "MyClass", "procedure_name": "my_method", "file": "path/to/File.m" } ]

其中bug_typeprocedure_namefile为必填定位信息,class_name按需给出,comment用于说明屏蔽理由。

--report-suppress-errors +error_name直接不报告指定类型(error_name)的错误。

--report-force-relative-path强制把绝对路径转换为相对于根目录的路径(对应--no-report-force-relative-path)。

--pmd-xml开启后,问题同时以 PMD XML 格式输出到infer-out/report.xml(对应--no-pmd-xml)。

--sarif开启后,问题以 SARIF(Static Analysis Results Interchange Format,静态分析结果交换格式)输出到infer-out/report.sarif(对应--no-sarif)。SARIF 是 GitHub 等平台通用的代码扫描结果标准格式。

--no-report分析完成后不执行报告阶段(对应--report)。适合只关心分析中间结果、想自己解析infer-out内部文件的场景。

3.3 调试与诊断

--debug, -g激活调试模式,等价于一次性设置:--debug-level 2--developer-mode--print-buckets--print-types--reports-include-ml-loc--no-only-cheap-debug--trace-error--write-html。反向开关为--no-debug | -G

--debug-level level设置全局调试级别,会同时设置--bo-debug level--debug-level-analysis level--debug-level-capture level

  • 0:仅启用基础调试
  • 1:启用详细调试(verbose)
  • 2:启用非常详细的调试(very verbose)

--debug-level-analysis int/--debug-level-capture int/--debug-level-report int分别针对分析、抓取、报告三个阶段独立设置调试级别,取值语义同--debug-level

--print-logs同时把日志输出到 stdout 和 stderr(对应--no-print-logs)。

--no-progress-bar, -P关闭进度条显示(对应--progress-bar | -p)。

--timeout float任一检查器分析单个函数/方法的最大时间,单位秒,默认 120 秒。超时后该函数被跳过,防止个别复杂函数拖垮整个分析。

--version/--version-json分别以纯文本与 JSON 格式打印版本信息并退出。

--help/--help-format { auto | groff | pager | plain }/--help-full

  • --help:显示本手册;
  • --help-format:指定帮助输出格式,auto在环境变量TERMdumb或未定义时使用plain,否则使用pager
  • --help-full:显示含 INTERNAL OPTIONS(内部选项)部分的完整手册。

3.4 运行行为控制

--fail-on-issue若 Infer 发现了需要报告的问题,则以退出码 2 退出(对应--no-fail-on-issue)。该选项在 CI 流水线中极为常用:配合infer run的一体化流程,echo $?即可判断本次分析是否引入新问题。

--force-delete-results-dir即使目标目录看起来不像 Infer 的 results 目录,也允许删除它(对应--no-force-delete-results-dir)。默认 Infer 会拒绝删除"非 infer 生成"的目录以保护用户数据。

--force-integration command强制把--之后的第一个参数当作指定的构建集成命令处理。可取值包括:antbuckbuck2gradlegradlewjavajavackotlincccclanggccclang++c++g++hackcmakeconfigurecmakewafmvnmvnwndk-buildpython3rebar3rustcswiftcerlcxcodebuild。当构建命令名不标准或需绕过自动探测时使用。

--never-returning-null json[仅 Java,适用于所有分析] Matcher 或 matcher 列表,声明这些函数永远不会返回null,供分析器消解空值告警。

--project-root, -C dir指定项目根目录。报告过滤相关的路径正则均以该目录为基准(相对路径)。

--results-dir, -o dir指定结果及内部文件的写入目录,默认infer-out

--skip-analysis-in-path +regex忽略路径匹配给定正则的文件(可多次指定,但需确保每个正则正确加括号转义)。注意该选项只跳过分析,不影响抓取。

--停止参数解析,其后的所有参数被视为构建命令。

3.5 SQLite 结果数据库调优

infer run的分析结果会写入 SQLite 数据库,手册提供以下底层调优选项(对应 SQLite PRAGMA 语义):

  • --sqlite-cache-size int:SQLite 缓存大小,单位为页(正数)或 kB(负数);
  • --sqlite-lock-timeout int:SQLite 结果数据库操作的锁超时时间,单位毫秒;
  • --sqlite-max-blob-size int:写入 SQLite 的最大 blob/字符串大小;
  • --sqlite-mmap-size int:mmap 映射 SQLite 数据库的内存大小,0 表示禁用内存映射;
  • --sqlite-page-size int:SQLite 页大小(字节),必须是 512 到 65536 之间的 2 的幂。

这些选项在并行分析大规模项目、需要精细控制内存占用时非常有用。

3.6 Buck 集成选项

当 Infer 与 Facebook 的 Buck 构建系统配合使用时,infer run额外提供:

--buck-targets-block-list +regex跳过被该正则匹配的 Buck target 的抓取。

--buck2-bxl-capture-file-block-list +regex跳过被该正则匹配的文件的抓取。仅支持 Clang + Buck2 集成,不支持 Java

--buck2-root dir指定buck-out的父目录(仅用于 buck2)。

3.7 Pulse 检查器选项

--pulse-report-issues-reachable-from +regex将 Pulse 能够一路传播到匹配某正则的过程(procedure)的问题重新上报。Pulse 是 Infer 的分离逻辑(separation logic)分析器,其默认行为会抑制中间传播路径上的问题;该选项用于在问题最终"冒出"到指定入口函数(例如 main 或测试入口)时将其重新暴露出来。

四、环境变量与.inferconfig配置文件

infer run的 ENVIRONMENT 与 FILES 部分指向infer(1)手册的对应章节(详见 infer/man/man1/infer.txt#L2603-L2644),以下为要点:

环境变量

  • INFER_ARGS:以^分隔的额外选项字符串,会被应用到所有 infer 命令。例如INFER_ARGS=--debug^--print-logs infer等价于infer --debug --print-logs。注意运行时会打印INFER_ARGS = ...以便排查(见 infer/src/infer.ml#L91-L98)。
  • INFERCONFIG:指定.inferconfig配置文件的查找位置。
  • INFER_STRICT_MODE:设为"1"后,infer 命令在某些本应仅在 stderr 输出警告的场合(例如使用了某个选项的废弃形式)会改为以错误码退出。

.inferconfig文件

.inferconfig用于持久化 infer 选项,格式为 JSON 记录:字段名是 infer 长选项去掉--后的名字,值的类型取决于选项类型:

  • 开关型选项:JSON 布尔值(true/false,不带引号);
  • 无参数的非开关选项(如列表选项对应的...-reset):null
  • 整数选项:JSON 整数(不带引号);
  • 字符串选项:JSON 字符串;
  • 路径选项:JSON 字符串,且相对于.inferconfig文件所在位置解释;
  • 累积型(cumulative)选项:相应类型的 JSON 数组。

手册给出官方示例:

{ "cxx": false, "infer-block-list-files-containing": ["@gen", "/* no infer */"] }

查找顺序:先看命令行--inferconfig-path指定的文件;否则读INFERCONFIG环境变量指定的文件;再否则从当前目录向上逐级查找第一个.inferconfig。整体优先级为:命令行参数 >INFER_ARGS>.inferconfig(详见 infer/man/man1/infer.txt#L36-L40 的 OPTIONS 说明)。

五、与相关命令的关系

infer run手册的 SEE ALSO 一节指向三个最密切的命令(对应手册分别位于 infer/man/man1/ 下):

  • infer capture(1):只抓取,不分析,等价于infer run --no-analyze的拆分形式;
  • infer analyze(1):只分析已抓取的结果,对应infer run的第二阶段;在 infer/src/infer.ml#L134-L137 中Analyze直接调用Driver.run Analyze
  • infer report(1):只对已有结果生成报告(支持--pmd-xml--sarif、报告过滤等选项的独立执行形态)。

实际工程中,典型的增量工作流是:CI 首次运行infer run -- <编译命令>得到全部结果;后续迭代使用infer capture -- <编译命令>(复用.inferconfig中的过滤配置)与infer analyzeinfer report分段执行,借助--fail-on-issue--report-block-list-spec等选项把已知误报纳入管理,从而在不重新抓取的前提下反复调整报告口径。手册完整的选项清单与最新定义,可随时通过infer run --help(或--help-full查看内部选项)获取。

  • 静态分析
  • 代码质量
  • 开发工具

【免费下载链接】infer

A static analyzer for Java, C, C++, and Objective-C

项目地址:https://gitcode.com/gh_mirrors/infer/infer
点击查看免费下载

相关推荐

上一篇:pin-project实战案例:如何优雅处理Rust中的固定类型
下一篇:InstructIR本地部署教程:在你的GPU上搭建高性能图像修复工作站

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 15:34:54

实时仿真机SimuDev

1&#xff09;产品简介SimuDev实时仿真机产品系列&#xff0c;适用于微秒级步长仿真及测试需求的应用场合。SimuDev是基于多核CPUFPGA架构的高性能实时仿真平台&#xff0c;方便与实际设备连接进行快速原型验证和硬件在环测试。2&#xff09;技术特点提供RS232、RS422、RS485各…

作者头像 李华
网站建设 2026/9/24 15:34:29

工业振动传感器选型12个生死问题:温度、冲击、EMI全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 15:34:14

手撸 SpringBoot 脚手架:用 FreeMarker 模板引擎构建企业级工程框架

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总&#xff0c;旨在为大家提供一个清晰详细的学习教程&#xff0c;侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助&#xff0c;请给予支持(关注、…

作者头像 李华