【问题标题】:Avoiding, finding and removing memory leaks in Cocoa避免、发现和消除 Cocoa 中的内存泄漏
【发布时间】:2010-09-15 09:17:25
【问题描述】:

发生内存(和资源)泄漏。你如何确保他们没有?

您会建议哪些技巧和技术来帮助避免首先造成内存泄漏?

一旦您的应用程序发生泄漏,您如何追踪泄漏源?

(哦,请避免“只使用 GC”的答案。在 iPhone 支持 GC 之前,这不是一个有效的答案,即使那样 - 可能会在 GC 上泄漏资源和内存)

【问题讨论】:

    标签: objective-c cocoa debugging macos memory


    【解决方案1】:
    • 遵循保留和释放规则(或使用垃圾收集)。 They're summarized here.

    • 使用仪器追踪泄漏。您可以使用 Xcode 中的 Build > Start With Performance Tool 在 Instruments 下运行应用程序。

    【讨论】:

    • 好答案。这两个技巧绝对是解决方案的一部分。我希望这篇文章成为内存泄漏调试的完整 A-Z。我们会看看这是否会发生。 ;-)
    • 我认为 ARC 内存泄漏应该不是问题。我怎么还能拥有它?
    • ARC 自动发送保留和释放消息,但您仍然必须考虑保留对象图并确保不会发生对象相互引用的循环。您可以使用 @property(weak) 或 __weak 来防止这种情况发生。
    【解决方案2】:

    Instruments Leaks 工具非常擅长发现某种类型的内存泄漏。只需使用“Start with Performance Tool”/“Leaks”菜单项即可通过此工具自动运行您的应用程序。适用于 Mac OS X 和 iPhone(模拟器或设备)。

    Leaks 工具可帮助您找到泄漏源,但对追踪泄漏内存的保留位置没有太大帮助。

    【讨论】:

      【解决方案3】:

      我记得不久前我使用 Omni 的一个工具,当时我试图追踪一些内存泄漏,这些泄漏会显示对象上的所有保留/释放/自动释放调用。我认为它显示了分配的堆栈跟踪以及对象上的所有保留和释放。

      http://www.omnigroup.com/developer/omniobjectmeter/

      【讨论】:

        【解决方案4】:

        在 XCode 4.5 中,使用内置的Static Analyzer

        在 3.3 之前的 XCode 版本中,您可能需要下载静态分析器。这些链接向您展示了如何:

        使用 LLVM/Clang 静态分析器

        为避免一开始就造成内存泄漏,请使用Clang Static Analyzer -- 不出所料 -- 在 Mac OS X 10.5 上分析您的 C 和 Objective-C 代码(还没有 C++)。安装使用很简单:

        1. this page下载最新版本。
        2. 从命令行,cd 到您的项目目录。
        3. 执行scan-build -k -V xcodebuild

        (还有一些额外的限制等,特别是您应该在其“调试”配置中分析一个项目——有关详细信息,请参阅http://clang.llvm.org/StaticAnalysisUsage.html——但这或多或少是归结为的。)

        分析器随后会为您生成一组网页,其中显示可能的内存管理和编译器无法检测到的其他基本问题。

        如果您的项目不针对 Mac OS X 桌面,还有一些其他细节:

        1. 将 Base SDK for All Configurations 设置为使用 Mac OS X 桌面框架的 SDK...
        2. 将命令行构建设置为使用调试配置。

        (这与this question 的答案基本相同。)

        【讨论】:

        • 您好,先生,您的链接已失效。你能编辑和修复吗?
        【解决方案5】:

        始终使用访问器方法;使用属性声明访问器

        如果您总是使用访问器方法为实例变量赋值(init*dealloc 方法除外),那么您自己的生活就会变得更加简单。除了确保正确触发任何副作用(例如KVO change notifications)之外,与使用@987654325 撒上代码相比,它使您遭受复制粘贴或其他一些逻辑错误的可能性要小得多@s 和releases。

        在声明访问器时,您应该始终使用Objective-C 2 properties 功能。属性声明使访问器的内存管理语义明确。它们还为您提供了一种简单的方法来交叉检查您的 dealloc 方法,以确保您已释放您声明为 retaincopy 的所有属性。

        【讨论】:

          【解决方案6】:

          不要过度考虑内存管理

          出于某种原因,许多开发人员(尤其是早期开发人员)使自己的内存管理比以往任何时候都更加困难,通常是通过过度思考问题或想象问题比实际情况更复杂。

          fundamental rules 非常简单。您应该只专注于遵循这些。不要担心其他对象可能会做什么,或者您的对象的保留计数是多少。相信其他人都遵守相同的合同,这一切都会正常工作。

          特别是,我将重申不要担心对象的保留计数这一点。由于各种原因,保留计数本身可能会产生误导。如果您发现自己记录了对象的保留计数,则几乎可以肯定您走错了路。退一步问问自己,你是否遵守基本规则?

          【讨论】:

          【解决方案7】:

          首先,您对 [ ] 和 { } 括号和大括号的使用符合通用标准非常重要。好吧,开个玩笑。

          查看泄漏时,您可以假设泄漏是由于代码中的问题造成的,但这并不是 100% 的错误。在某些情况下,Apple 的(喘气!)代码中可能发生了错误。而且它可能很难找到,因为它不会显示为被分配的可可对象。我过去曾向 Apple 报告过泄漏错误。

          泄漏有时很难找到,因为您发现的线索(例如,数百个字符串泄漏)可能不是因为直接导致字符串泄漏的那些对象正在泄漏,而是因为某些东西正在泄漏 那个 对象。通常,您必须挖掘泄漏的“树”的叶子和树枝才能找到问题的“根源”。

          预防:我的主要规则之一是真的,真的,真的避免分配一个对象,而不是当场自动释放它。任何你分配/初始化一个对象然后在代码块中释放它的地方都是你犯错的机会。要么你忘记释放它,要么你抛出一个异常以使释放永远不会被调用,或者你在方法的某处放置一个“return”语句以提前退出(我也尽量避免)。

          【讨论】:

          【解决方案8】:

          您可以从这里构建 Valgrind 的 beta 端口:http://www.sealiesoftware.com/valgrind/

          它比任何静态分析都有用得多,但据我所知,它还没有任何特殊的 Cocoa 支持。

          【讨论】:

            【解决方案9】:

            显然,您首先需要了解基本的内存管理概念。但在追查泄漏方面,我强烈建议阅读this tutorial on using the Leaks mode in Instruments

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-04-08
              • 2013-06-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-09-23
              相关资源
              最近更新 更多