我让 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 生成的代码时。

Back to Blog

相关文章

阅读更多 »