[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fKR9DrsKSx_tDdCvbmRTmKFxRH5Vm2n1p_yujwIJ8Jc0":3},{"item":4,"related":48},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":39,"sourceName":40,"sourceUrl":41,"status":42,"seoTitle":7,"seoDescription":9,"canonicalUrl":39,"isFeatured":43,"sno":44,"sortOrder":45,"publishedAt":46,"updatedAt":47,"createdAt":47},"990d763f-115c-4589-9e7d-769d9050410e","article","SMT Solver：让机器回答“有没有满足这些条件的输入”","smt-solver-z3-constraints-explained","SMT Solver 专门处理带有整数、数组、位向量和逻辑条件的可满足性问题。本文以 Z3 为例，解释模型、反例和不可满足的含义，说明约束求解器如何帮助程序验证、测试生成和 AI 编程。","很多程序问题都可以改写成一句话：“有没有一个输入，同时满足这些条件？”比如，能不能找到让数组越界的参数？两个时间区间有没有重叠？某个权限组合是否会绕过检查？SMT Solver，也就是可满足性模理论求解器，就是专门处理这类带有整数、数组、位向量、函数和逻辑条件的问题。\n\n## 它和普通计算器有什么区别\n\n计算器擅长计算一个已经确定的表达式，SMT 求解器则处理未知数和约束。例如，`x + 3 = 10` 很容易求出 `x`，但当条件包含数组读写、位运算、字符串或多个相互依赖的变量时，单纯代数就不够了。\n\n以 Z3 为例，程序分析工具可以把代码中的分支条件翻译成求解器能理解的逻辑公式，再询问公式是否可满足。如果可满足，求解器可能返回一个模型，也就是一组能满足条件的变量取值；如果不可满足，则说明在当前约束下不存在这样的输入。\n\n## “不可满足”不等于“程序绝对安全”\n\n求解器只对送给它的模型负责。如果工具遗漏了一个外部函数、错误表达了整数溢出，或没有把真实环境约束加入公式，那么结果只代表这个简化模型。\n\n这也是形式化工具中最容易被忽略的边界：数学推理可以非常严格，但前提必须准确。工程上通常会把求解器当作程序分析、符号执行、验证和测试生成的一个组件，而不是单独的安全认证。\n\n## 它和 AI 编程有什么关系\n\nAI 很擅长提出“看起来合理”的代码，但不擅长穷举所有边界条件。SMT 求解器可以把代码中的条件变成可检验的问题，帮助生成反例、验证简单不变量，或检查两个实现是否在给定语义下等价。\n\n普通读者不需要掌握求解器内部的搜索算法，只要理解一个关键区别：它不是预测一个最可能的答案，而是在约束空间里寻找满足条件的证据，或者证明当前条件没有解。\n\n## 读者应该记住\n\nSMT Solver 的核心价值，是把“我觉得这段代码没问题”改写成“是否存在一个反例”。AI 负责生成候选方案，求解器负责在明确模型里寻找证据，两者结合才更接近可靠的自动编程。\n\n资料：[Microsoft Research：Z3](https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fresearch\u002Fproject\u002Fz3-3\u002F)；[Z3 Guide](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fz3guide)","\u002Fuploads\u002F2026-09-20\u002F457baa75-2391-4085-8348-996f2420b162.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31,35],{"id":24,"name":25,"slug":26},"88d2bc27-0e0f-468a-b907-2991cb97b87b","人工智能","ai",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":32,"name":33,"slug":34},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":36,"name":37,"slug":38},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"Microsoft Research：Z3","https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fresearch\u002Fproject\u002Fz3-3\u002F","published",false,58,0,"2026-09-20T00:00:00.000Z","2026-09-20T03:57:47.026Z",[49,57,66],{"id":50,"type":6,"title":51,"slug":52,"summary":53,"coverUrl":54,"authorName":14,"sno":55,"publishedAt":46,"createdAt":56},"55f81c45-2885-485f-94b4-333c3f850f09","E-graphs：AI 如何同时保留一百种等价写法，最后挑出最好的？","e-graphs-equality-saturation-explained","E-graph 把许多语义等价的表达式放在同一张图里，等候选方案足够丰富后，再依据速度、体积或能耗统一选择。本文用地铁换乘图解释 equality saturation，说明它为什么适合编译器、查询优化，也能启发 AI 编程先保留方案再做决策。","\u002Fuploads\u002F2026-09-20\u002Fe9999469-64b1-4d20-a4c9-b3ba1f10ac27.jpg",47,"2026-09-20T03:57:41.871Z",{"id":58,"type":6,"title":59,"slug":60,"summary":61,"coverUrl":62,"authorName":14,"sno":63,"publishedAt":64,"createdAt":65},"5e0c84da-6011-41e8-b1f7-726c8bf0b30a","RCU：读多写少的系统，为什么敢让读者几乎不加锁？","rcu-read-copy-update-explained","RCU 把共享数据的更新与旧版本回收拆开，让读者以极低成本读取，同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。","\u002Fuploads\u002F2026-09-26\u002F3398ce37-ca4f-4cc3-84b3-fe931d2f055d.jpg",41,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:40.784Z",{"id":67,"type":6,"title":68,"slug":69,"summary":70,"coverUrl":71,"authorName":14,"sno":72,"publishedAt":73,"createdAt":74},"0bc79f1c-f305-4d64-a9f8-589d1d6da0b3","EEVDF：Linux 如何判断哪个任务“最该先用 CPU”？","eevdf-linux-fair-cpu-scheduling","EEVDF 是 Linux 调度器的一种公平调度思路：先判断任务是否获得了应有份额，再按虚拟截止时间安排运行机会。本文用共享厨房的比喻，解释它如何兼顾长期公平与短期响应，并澄清它并非硬实时保证。","\u002Fuploads\u002F2026-10-13\u002Fdc59d374-8c78-41ba-bdfe-a6f0e62ab246.jpg",43,"2026-10-13T00:00:00.000Z","2026-10-13T02:13:28.103Z"]