[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ft19vq8PBYr9ZR73RR7wV58YmTvKT9KEL9zNv6yhnxyg":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},"6404d41a-6276-4ad4-9d36-d974ef59cd37","article","Symbolic Execution：把输入变成未知数，程序能自己找出崩溃条件吗？","symbolic-execution-program-paths-explained","Symbolic Execution 不只用几个样例运行程序，而是把输入当成未知变量，记录每条路径的条件，并尝试构造能触发越界或崩溃的具体输入。本文解释路径爆炸、模型边界，以及它如何辅助 AI 生成代码的安全检查。","测试一个程序时，最常见的做法是准备若干具体输入：空字符串、很长的字符串、正常账号和异常账号。Symbolic Execution 则把输入当成未知变量，让程序沿着不同分支运行，并把每条路径上的条件记录成约束。这样，工具不仅能告诉你“这里可能出错”，还可能给出一组触发错误的输入条件。\n\n## 具体输入和符号输入\n\n考虑一个简单函数：当 `x > 10` 时访问数组的第一个位置，否则访问第二个位置。用具体输入运行，只能走其中一条路。用符号变量 `x` 运行，执行器会分成两条路径，并分别记录 `x > 10` 与 `x \u003C= 10`。\n\n如果后续代码又要求 `x` 必须小于 0，某条路径的条件就可能变成矛盾；如果访问下标要求 `x` 在数组范围之外，约束求解器便可能构造出一个能触发越界的具体数字。\n\n## 它为什么不会无限分支\n\n符号执行最大的困难是路径爆炸。一个程序里有很多 `if`、循环和递归，路径数量可能呈指数增长。实际工具会采用边界限制、路径合并、状态缓存、随机搜索和优先级策略，把资源集中在更可能发现问题的路径上。\n\n符号值本身也有边界。字符串、系统调用、浮点数和外部服务很难完全用简单数学表达。工具往往需要模型化这些环境，或者在符号分析和具体执行之间切换。\n\n## 在安全和 AI 编程里的位置\n\n符号执行常用于发现崩溃、越界、整数溢出和某些安全漏洞。对 AI 生成代码，它可以成为测试之外的一层检查：不是只问“这几个样例通过了吗”，而是询问“在什么条件下，这段代码会走到危险路径”。\n\n但它不是万能证明器。工具覆盖的路径受到时间、内存、模型精度和程序结构限制。一个没有被发现的 bug，不代表所有输入都安全；一个被发现的路径，也还需要工程师判断是否能在真实环境中复现。\n\n## 读者应该记住\n\nSymbolic Execution 的直觉很简单：把“输入一个数字”变成“输入满足某些条件的任意数字”，让程序自己暴露路径约束。它把测试从样例驱动，推进到条件驱动。\n\n资料：[KLEE 官方文档](https:\u002F\u002Fklee-se.org\u002Fdocs\u002F)；[KLEE 项目](https:\u002F\u002Fgithub.com\u002Fklee\u002Fklee)","\u002Fuploads\u002F2026-09-20\u002Ffe785363-a081-411b-bd2e-e191c0f0d86e.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},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"07b0ad92-5bba-481c-a567-6ae6d32c2122","Bug","bug",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",{"id":36,"name":37,"slug":38},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",null,"KLEE 官方文档","https:\u002F\u002Fklee-se.org\u002Fdocs\u002F","published",false,44,0,"2026-09-20T00:00:00.000Z","2026-09-20T03:57:45.100Z",[49,58,67],{"id":50,"type":6,"title":51,"slug":52,"summary":53,"coverUrl":54,"authorName":14,"sno":55,"publishedAt":56,"createdAt":57},"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":59,"type":6,"title":60,"slug":61,"summary":62,"coverUrl":63,"authorName":14,"sno":64,"publishedAt":65,"createdAt":66},"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",{"id":68,"type":6,"title":69,"slug":70,"summary":71,"coverUrl":72,"authorName":14,"sno":44,"publishedAt":56,"createdAt":73},"23b5596a-29ab-4ff8-8237-1fd34d8e0bd1","Seqlock：读者不加锁，为什么还能读到一份一致的数据？","seqlock-sequence-counter-explained","Seqlock 让读者先后读取序列号并在变化时重试，以校验快照是否被写者打断，适合读多写少且字段可安全复制的数据。","\u002Fuploads\u002F2026-09-26\u002Fe6a9caee-7551-469f-9b16-d27fcc97f034.jpg","2026-09-26T16:25:51.305Z"]