Z3不能直接验证C++代码,因其是SMT求解器而非编译器或解析器;需手动将C++逻辑(如断言、循环不变量)翻译为SMT-LIB格式的逻辑公式再交由Z3求解。
Z3 不能直接验证 C++ 代码的正确性——它不解析 C++ 语法,也不执行或编译 C++ 程序。你要做的,是把 C++ 中的关键逻辑(比如循环不变量、函数前置/后置条件、断言)手动翻译成 Z3 能理解的逻辑公式,再交由 Z3 求解。
Z3 是一个 SMT 求解器,它处理的是已形式化的逻辑表达式(如:整数线性算术、位向量、数组、未解释函数等),不是源码分析器或编译器前端。它没有 C++ 词法分析器、语法树构建器或语义模型。
z3 命令行工具只接受 SMT-LIB v2 格式的文本(.smt2 文件)或通过 API 构造的表达式for (int i = 0; i 显式建模为归纳变量 + 不变量断言)
以一个简单函数为例:
int abs_diff(int a, int b) {
return (a > b) ? a - b : b - a;
}你想验证:对所有整数 a, b,结果非负且等于 |a - b|。
你需要做三件事:
Int 类型声明两个变量:a, b
res,并添加分支等价约束:Or(And(a > b, res == a - b), And(a
Not(res >= 0);若 Z3 返回 unsat,说明该性质恒成立Python + z3py 示例:
立即学习“C++免费学习笔记(深入)”;
from z3 import *
a, b, res = Int('a'), Int('b'), Int('res')
s = Solver()
s.add(Or(And(a > b, res == a - b), And(a <= b, res == b - a)))
s.add(res < 0) # 否定待证性质
print(s.check()) # 输出 unsat → 性质成立
实际工程中卡住的地方往往不是 Z3 用法,而是建模本身:
BitVec(32) 并重写所有运算new/delete)、函数指针、虚函数调用无法直接建模;只能抽象为未解释
函数(Function('malloc', IntSort(), IntSort())),但会大幅削弱验证力度Implies 表达“进入前成立 ⇒ 执行一次后仍成立”FPSort(8, 24)(单精度)等,且需启用 fp 理论,而 C++ float 的实际行为(如 FMA、舍入模式)仍需额外建模真正能落地的场景,是小而关键的算法模块(如加密辅助函数、协议解析边界检查、ring buffer 索引计算),配合人工提取的规约。指望 Z3 “全自动验证整个 C++ 项目”,目前只是论文标题里的动词。