news 2026/2/18 4:35:46

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/2/16 8:31:00

2026软件测试爆款指南:性能瓶颈手动检查实战与热点嫁接策略

性能测试的痛点与公众号热度交汇点 软件测试从业者常面临性能瓶颈的隐形威胁——从系统延迟到资源耗尽&#xff0c;这些问题不仅影响用户体验&#xff0c;还可能导致业务损失。 与此同时&#xff0c;公众号内容热度显示&#xff0c;2026年测试从业者最关注实操性强、数据驱动的…

作者头像 李华
网站建设 2026/2/16 8:28:00

打卡信奥刷题(2788)用C++实现信奥题 P3938 斐波那契

P3938 斐波那契 题目背景 大样例可在页面底部「附件」中下载。 题目描述 小 C 养了一些很可爱的兔子。 有一天&#xff0c;小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行 繁衍&#xff1a;一对兔子从出生后第二个月起&#xff0c;每个月刚开始的时候都…

作者头像 李华
网站建设 2026/2/16 10:08:05

打卡信奥刷题(2790)用C++实现信奥题 P3941 入阵曲

P3941 入阵曲 题目背景 pdf题面和大样例链接&#xff1a;http://pan.baidu.com/s/1cawM7c 密码&#xff1a;xgxv 丹青千秋酿&#xff0c;一醉解愁肠。 无悔少年枉&#xff0c;只愿壮志狂。 题目描述 小 F 很喜欢数学&#xff0c;但是到了高中以后数学总是考不好。 有一天&…

作者头像 李华
网站建设 2026/2/16 18:18:59

为AI代理设计分层记忆

想象一个不仅仅是响应&#xff0c;而是记忆的AI。一个能够从过去的交互中学习、理解复杂关系、并从一个深邃的知识之井中提取事实的AI。这不是科幻小说&#xff1b;这是代理AI的承诺——而它的秘密武器在于一个复杂的、多层次记忆系统。 大语言模型&#xff08;LLMs&#xff0…

作者头像 李华
网站建设 2026/2/17 3:56:05

Android Jetpack Compose - 进度指示器、SegmentedButton、Chip

一、进度指示器 1、基本介绍 进度指示器可以分为 2 种类型类型说明确定型准确显示已完成的进度不确定型持续动画显示&#xff0c;不考虑进度进度指示器可以采用 2 种形式类型说明线性从左向右填充的水平条圆形笔画长度不断增加&#xff0c;直到覆盖整个圆周的圆2、基本使用 var…

作者头像 李华
网站建设 2026/2/11 6:45:45

AI产品经理破局之道:5大提问框架,让业务经验变AI燃料,建议收藏

AI产品经理常陷入业务与技术间的沟通困境&#xff0c;核心问题是业务拥有隐性知识&#xff0c;而AI需要显性规则。突破之道在于角色转变&#xff1a;从接需求到主动挖矿&#xff0c;从推销方案到定义问题&#xff0c;从交付功能到交付认知&#xff0c;从会议室专家到一线学徒。…

作者头像 李华