[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f5kzJ3Tw0Gohg8p4lVh8s7KEGoWfPaJaEZgPDiYR83R8":3},{"item":4,"related":51},{"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":43,"seoDescription":44,"canonicalUrl":45,"isFeatured":46,"sno":47,"sortOrder":48,"publishedAt":49,"updatedAt":50,"createdAt":50},"720726db-e391-432c-b980-5652f6bc132c","article","CFG：程序不是一条线，而是一张路网","control-flow-graph-ai-code-analysis","控制流图 CFG 把条件、循环和异常路径画成程序路网，帮助理解 AI 调试、分支覆盖与静态分析。","## CFG：程序不是一条线，而是一张路网\n\n代码从上到下排列，但运行时并不一定从第一行走到最后一行。`if`、`for`、`while`、异常和提前返回都会改变路线。CFG，也就是 Control-Flow Graph，控制流图，就是用节点和边表示程序可能执行路径的一种模型。\n\n## 节点和边分别是什么\n\n控制流图中的节点通常是基本块：一组连续执行、不会从中间跳入或跳出的指令。边表示执行可能从一个基本块走向另一个基本块。一个 `if` 会产生至少两条分支，循环则会形成回边，表示程序可能回到之前的节点。\n\n这张图能回答许多单纯看文本不容易回答的问题：某行代码是否可达？某个异常处理是否永远不会触发？一个分支是否从未被测试？函数退出前是否所有路径都返回了值？\n\n## AI Agent 为什么需要路径视角\n\nAI 常见的修复方式是看到一个报错就改附近几行，但真正的原因可能在另一条路径上。例如模型为一个变量补了默认值，却没有注意到另一个分支会绕过初始化；或者它只修复了正常流程，遗漏了超时和异常流程。控制流图能把“可能怎么走”显式化。\n\n对 AI 生成测试来说，CFG 也很重要。测试不只是覆盖函数名，更要覆盖分支和边。一个测试套件即使调用了每个函数，也可能始终只走成功路径。覆盖率工具常通过对基本块和边进行插桩，记录真实执行过的路线。\n\n## CFG 和业务流程不是一回事\n\n控制流图表达的是程序执行可能性，不代表用户实际会怎样操作。某条路径在语法上可达，不等于业务上允许；某条异常路径很少触发，也不等于它不重要。AI 仍然需要产品规则、输入约束和真实场景来判断优先级。\n\n## 普通开发者可以怎样使用\n\n让 AI 修复复杂 Bug 时，可以要求它先列出触发问题的完整路径：输入从哪里来，经过哪些条件，在哪个节点出错，修复后哪些分支需要补测。这样做会迫使模型从“改一行”转向“解释一条路”。\n\n关于基本块、边和覆盖率插桩，可以参考 [Clang SanitizerCoverage 文档](https:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FSanitizerCoverage.html)。","\u002Fuploads\u002F2026-09-14\u002F9b0d8585-95dc-4910-9336-adb607b859cb.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},"0848beb4-db26-4fb8-b391-f852a11be192","AI编程","ai-coding",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",{"id":36,"name":37,"slug":38},"07b0ad92-5bba-481c-a567-6ae6d32c2122","Bug","bug","官方资料","Clang SanitizerCoverage","https:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FSanitizerCoverage.html","published","CFG 控制流图是什么？AI 调试为什么要看执行路径","从 if、循环和异常开始理解控制流图，以及它如何帮助 AI 编程发现遗漏分支。",null,false,50,0,"2026-09-14T00:00:00.000Z","2026-09-14T15:01:32.411Z",[52,61,69],{"id":53,"type":6,"title":54,"slug":55,"summary":56,"coverUrl":57,"authorName":14,"sno":58,"publishedAt":59,"createdAt":60},"7cc644a5-e0de-4d7b-802e-9e8b69677e12","AI 生成的代码会不会复制开源项目","ai-code-open-source-reference-license","AI 生成代码不等于天然没有来源。本文区分常见写法与高相似片段，解释代码引用、许可证、依赖供应链和轻量来源检查，帮助团队把合规当成代码质量的一部分。","\u002Fuploads\u002F2026-09-13\u002F920327ad-de7f-4caa-a2f4-816d467c9f9c.jpg",40,"2026-09-13T00:00:00.000Z","2026-09-13T11:55:49.911Z",{"id":62,"type":6,"title":63,"slug":64,"summary":65,"coverUrl":66,"authorName":14,"sno":67,"publishedAt":59,"createdAt":68},"1ff2b0c1-c125-4469-a09c-b8ddbc5bf705","AI 写 SQL 和数据库迁移，为什么必须人工确认","ai-generated-sql-database-migrations","数据库迁移会改变持久数据、锁和应用契约，语法正确不代表上线安全。本文解释 AI 生成 SQL 的风险，介绍扩展、迁移、收缩的兼容策略，以及生产执行前应检查的门槛。","\u002Fuploads\u002F2026-09-13\u002F6e5177d7-f51a-4722-951b-0108e9b7ecae.jpg",41,"2026-09-13T11:55:59.196Z",{"id":70,"type":6,"title":71,"slug":72,"summary":73,"coverUrl":74,"authorName":14,"sno":67,"publishedAt":59,"createdAt":75},"88cd83c5-bb5f-411a-85bf-1eefdcacebf4","AI 代码审查能不能替代人类 Code Review","ai-code-review-human-review","AI 很适合做第一轮代码审查，却不一定理解业务语义、风险取舍和变更完整性。本文梳理 AI 审查的强项与盲区，并给出自动检查、AI 建议和人工批准的三层协作方式。","\u002Fuploads\u002F2026-09-13\u002F1ff872e2-ecfe-4bd4-9dd1-327a09a8f6dc.jpg","2026-09-13T11:55:47.724Z"]