我让 Claude 在任务中制造内存泄漏,但它失败了
发布: (2025年12月3日 GMT+8 15:43)
3 min read
原文: Dev.to
Source: Dev.to
背景
上周我让 Claude 为了好玩在 Swift 的 Task API 中制造一个内存泄漏。生成的代码声称 Task 强引用了 self,形成了循环引用,并建议使用 [weak self]。我知道这有点不对——Task 默认并不会产生循环引用,这正是它的设计优势之一。
调查
为了验证这个说法,我检查了 Swift 编译器的中间表示——SIL(Swift Intermediate Language)。SIL 精确展示了编译器在代码转化为机器码之前的行为,基本上相当于编译器的“笔记”。
相关 SIL 片段
%14 = function_ref @(extension in Swift):Swift.Task.init(priority: Swift.TaskPriority?, operation: __owned @isolated(any) () async -> A) -> Swift.Task : $@convention(method) (@in Optional, @sil_sending @owned @isolated(any) @async @callee_guaranteed @substituted () -> @out τ_0_0 for , @thin Task.Type) -> @owned Task // user: %15
%15 = apply %14(%3, %13, %2) : $@convention(method) (@in Optional, @sil_sending @owned @isolated(any) @async @callee_guaranteed @substituted () -> @out τ_0_0 for , @thin Task.Type) -> @owned Task // user: %17
dealloc_stack %3 : $*Optional // id: %16
release_value %15 : $Task // id: %17
%18 = tuple () // user: %19
return %18 : $() // id: %19
} // end sil function 'MemoryLeak.LeakyViewController.startLeakyTask() -> ()'
关键行是:
release_value %15 : $Task
这条指令表明 Task 的句柄在创建后立即被释放:
- Task 已创建
- Task 句柄立即释放
- Task 未被存储 → 视图控制器没有对其的强引用
- 没有循环引用 → 没有内存泄漏
你可以在 Swift 文档中阅读关于 release_value 指令的更多信息。
结论
SIL 分析证实 Task 不会 保持对视图控制器的引用,视图控制器的 deinit 将如预期般被调用。不存在内存泄漏。
有时候,了解事物工作原理的最佳方式是查看编译器实际执行的操作,而不是仅凭假设。信任,但要验证——尤其是在处理 AI 生成的代码时。