news 2026/6/5 22:35:04

Clang Static Analyzer Checker快速上手

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Clang Static Analyzer Checker快速上手

1. 环境背景

1. 虚拟机 Ubuntu20.4

2. llvm 15.0.7

2. 目标

在你的虚拟机中编写、编译并运行一个自定义的 Clang Static Analyzer Checker,使其能对一个简单的 C++ 文件输出自定义的警告信息。

3. 具体实现

1. 环境配置

克隆 LLVM 15.0.7 源码

cd ~ git clone --branch llvmorg-15.0.7 --depth 1 https://github.com/llvm/llvm-project.git

llvm-project目录下创建普通 build 目录(非build-arm),进行 x86/x64 架构的 CMake 配置和编译:

cd ~/llvm-project mkdir -p build && cd build # CMake 配置(普通编译,用于开发调试) cmake -G Ninja \ -DCMAKE_BUILD_TYPE=Debug \ -DLLVM_ENABLE_PROJECTS=clang \ -DLLVM_ENABLE_RTTI=ON \ -DLLVM_ENABLE_EH=ON \ ../llvm # 首次编译 Clang(耗时 1-2 小时,后续增量编译只需几分钟) ninja clang

检查是否生成了 clang 可执行文件

# 查看 bin 目录下是否有 clang、clang++ 可执行文件 ls -l bin/ | grep clang

验证通过标志

终端输出类似如下内容(能看到clangclang++,权限列包含x,表示可执行):

-rwxr-xr-x 2 user user xxxxxx 月 xx xx:xx clang -rwxr-xr-x 2 user user xxxxxx 月 xx xx:xx clang++

2. 在源码树中创建你的 Checker

编译验证通过后,就可以按照我们之前拆分的流程,开始创建和注册你的 Checker 了,核心步骤快速回顾(对应之前的细化内容,这里简化为执行路径):

阶段 1:创建 Checker 源码文件

1. 进入 Checkers 源码目录(直接复制执行):

cd ~/llvm-project/clang/lib/StaticAnalyzer/Checkers/

2. 新建并编写SimpleGraduationChecker.cpp

nano SimpleGraduationChecker.cpp

这是一个最小可行性代码。它不涉及复杂指针逻辑,仅仅检测代码中是否出现了名为test_function的函数调用。如果出现了,就报一个警。

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" using namespace clang; using namespace ento; namespace { // 定义一个Checker类,继承自Checker模板 // PreCall 表示我们要监听“函数调用前”这个事件 class SimpleGraduationChecker : public Checker<check::PreCall> { // 定义一个 BugType,用于分类报警 mutable std::unique_ptr<BugType> BT; public: // 这是核心回调函数,每次遇到函数调用都会进来 void checkPreCall(const CallEvent &Call, CheckerContext &C) const { // 1. 获取被调用函数的标识符 const IdentifierInfo *ID = Call.getCalleeIdentifier(); if (!ID) return; // 2. 检查函数名是不是 "test_function" if (ID->getName() == "test_function") { // 3. 如果是,准备报警 if (!BT) BT.reset(new BugType(this, "Graduation Project Check", "Custom Error")); // 4. 创建一个 BugReport // GenerateNonFatalErrorNode 创建一个解释节点,表示这里出了问题 ExplodedNode *N = C.generateNonFatalErrorNode(); if (!N) return; auto Report = std::make_unique<PathSensitiveBugReport>( *BT, "Warning: Found a dangerous call to test_function!", N); // 标记出错的代码位置 Report->addRange(Call.getSourceRange()); // 提交报告 C.emitReport(std::move(Report)); } } }; } // end anonymous namespace // 注册逻辑(照抄即可) void ento::registerSimpleGraduationChecker(CheckerManager &mgr) { mgr.registerChecker<SimpleGraduationChecker>(); } // 这是一个元数据函数,用于查询Checker是否应该被启用(通常直接返回true) bool ento::shouldRegisterSimpleGraduationChecker(const CheckerManager &mgr) { return true; }

阶段 2:修改两个配置文件(注册 Checker)

1. 修改同目录下的CMakeLists.txt

nano CMakeLists.txt

搜索.cpp找到文件列表,添加:SimpleGraduationChecker.cpp

在文件开头的头文件列表中添加:#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"

保存退出(Ctrl+O→ 回车 →Ctrl+X

2. 修改Checkers.td(注册表文件),注册 Checker 名称:

cd ~/llvm-project/clang/include/clang/StaticAnalyzer/Checkers/ nano Checkers.td

阶段 3:增量编译 Clang

进入build目录:

cd ~/llvm-project/build
  1. 进入build目录:
    cd ~/llvm-project/build
  2. 先构建自动生成文件和头文件目标(这一步会生成OMP.inc等文件,耗时几分钟):
    ninja llvm-headers clang-headers
  3. 若上述命令无报错,再额外构建clangStaticAnalyzerCheckers目标(你的 Checker 属于这个模块,直接构建该模块更精准):
    ninja clangStaticAnalyzerCheckers
  4. 最后再增量编译clang,确保所有依赖都生效:
    ninja clang

验证是否编译成功

验证 Checker 是否注册成功:

  1. ~/llvm-project/build/bin/clang -cc1 -analyzer-checker-help | grep graduation

预计输出如下:输出graduation.SimpleCheck

3 .运行测试

编译完成后,你的bin/clang就已经包含了你的 Checker。

准备测试代码
创建一个test.c文件:,这里我存在了~/Desktop/test.c下

void test_function() {} void safe_function() {} int main() { safe_function(); test_function(); // 这一行应该被报错 return 0; }

执行分析命令
使用-analyzer-checker参数指定我们在Checkers.td里定义的名字(假设是graduation.SimpleCheck):

~/llvm-project/build/bin/clang -cc1 -analyze -analyzer-checker=graduation.SimpleCheck ~/Desktop/test.c

执行结果如下:

到此为止,你已经成功打通了 Clang Static Analyzer(CSA)的完整开发流程,从源码修改、配置注册、增量编译到最终运行自定义检查器并输出警告,整个链路都跑通了。

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

什么是向量单位化 (vector normalization)

想象一下&#xff0c;向量就像一支箭头&#xff1a;它有方向&#xff08;箭头指向哪里&#xff09;&#xff0c;也有长度&#xff08;箭头有多长&#xff09;。比如在2D平面里&#xff0c;一个向量可以表示“向右走3步&#xff0c;再向上走4步”&#xff0c;写成 (3, 4)。这支箭…

作者头像 李华
网站建设 2026/5/29 2:16:55

乐天平台 (Rakuten) 数据采集指南

乐天平台数据采集存在两条核心路径&#xff1a;官方 Rakuten Web Service API 接入&#xff08;推荐&#xff0c;合法合规&#xff09;与非官方爬虫采集&#xff08;技术与法律风险并存&#xff09;。以下为完整方案与合规边界说明&#xff0c;适用于日本乐天市场 (Rakuten Ich…

作者头像 李华
网站建设 2026/5/31 10:43:01

5-FAM Maleimide,787632-00-2:高性能荧光标记试剂的核心解析

基本信息 英文名称&#xff1a;5-FAM Maleimide&#xff1b;5-FAM Mal&#xff1b;5-Carboxyfluorescein-MAL 中文名称&#xff1a;5-FAM马来酰亚胺&#xff1b;5-羧基荧光素-马来酰亚胺 CAS号&#xff1a;787632-00-2 分子式&#xff1a;C27H18N2O8 分子量&#xff1a;49…

作者头像 李华
网站建设 2026/5/30 15:19:55

68、Linux内核编译:从menuconfig配置到zImage生成全流程

Linux内核编译&#xff1a;从menuconfig配置到zImage生成全流程 一、核心概念先搞懂 1.1 关键术语解释 术语核心作用zImage压缩后的Linux内核镜像&#xff08;Image原始镜像 解压程序&#xff09;&#xff0c;体积小、启动快&#xff0c;适用于嵌入式设备menuconfigLinux内…

作者头像 李华