首页 > 解决方案 > iOS 内存泄漏,内存图调试器显示没有泄漏,但并行 Xcode-Instruments-leaks 显示泄漏

问题描述

在此处输入图像描述在我的项目中当我开始在内存图调试器中寻找泄漏时,我发现很少并修复了它们,现在内存图没有发现泄漏。Instruments->leaks 的问题,有时它显示泄漏,有时不显示,泄漏从一开始就立即出现,如照片中所述,我几乎不明白导致泄漏的原因。如果内存图显示没有泄漏,我可以相信它吗?或者存在一种未被内存图捕获的泄漏。我如何初始化 mainViewController 的代码:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow()
    
    let controller = MainViewController()
    let navigationController = UINavigationController(rootViewController: controller)
    let rootViewController = navigationController
    self.window?.rootViewController = rootViewController
    self.window?.makeKeyAndVisible()
           
    return true
        
}

标签: iosswiftmemory-leaksxcode-instrumentsmemory-graph-debugger

解决方案


在 2013 年的视频“修复内存问题”中,Apple 对“泄漏”、“废弃内存”和“缓存内存”进行了区分,如下所述。有关更多当代讨论,请参阅 WWDC 2021 视频检测和诊断内存问题、WWDC 2019 视频开始使用 Instruments和 WWDC 2018 视频iOS Memory Deep Dive

  • Leaked memory 是不能再次访问的内存,没有留下任何引用的内存,即已经malloc'ed 但从未free'd 的内存。

  • 废弃内存由确实有引用但不会再次访问的内存组成。

  • 缓存内存是可能不会再次使用的内存,保存在内存中以便在应用再次需要时快速检索。

“调试内存图”擅长发现和可视化由强引用周期引起的问题。“泄漏”工具不会识别这些问题。由于强引用循环等在 Swift 代码中更为普遍,“调试内存图”通常是更有成效的第一道防线。

在调试内存问题时,我们在循环浏览应用程序时不太担心第一次和第二次迭代之间的内存使用情况,而是关注后续迭代。

无论如何,“Leaks”工具和“debug memory graph”关注的是不同的问题,会产生不同的结果。泄漏没有找到强参考周期。同时,“调试内存图”功能在发现传统泄漏方面已经变得更好。

FWIW,在 Swift 中,强引用循环比传统的 - 但没有 - 泄漏更malloc常见free。除非您开始研究手动分配缓冲区、非托管 Core Foundation API 等,否则您的 Swift 代码不太可能出现传统泄漏。

如果你在你的应用程序中看到内存增长,在你担心泄漏之前,请确保它不是上述视频中确定的第三个内存问题,即缓存内存,它可能不会再次使用,但会自动回收设备内存不足。


顺便说一句,偶尔会报告隐藏在操作系统或框架中的泄漏。如果 (a) 您没有看到堆栈跟踪中引用了您的目标;或(b)泄漏是无关紧要的,那么我可能建议不要太担心它们。在您的情况下,我们谈论的是 384 字节,我不会太担心。


推荐阅读