19

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

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

一旦你有一个泄漏的应用程序,你如何追踪泄漏源?

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

4

9 回答 9

21

在 XCode 4.5 中,使用内置的静态分析器

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

使用 LLVM/Clang 静态分析器

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

  1. 从此页面下载最新版本。
  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. 将命令行构建设置为使用调试配置。

(这与这个问题的答案基本相同。)

于 2008-10-05T16:39:28.153 回答
16

不要过度考虑内存管理

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

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

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

于 2008-10-05T17:16:29.670 回答
10

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

init*如果您总是使用访问器方法将值分配给实例变量(除了 in和dealloc方法),那么您自己的生活就会变得更加简单。除了确保正确触发任何副作用(例如KVO 更改通知retain)之外,与使用s 和releases。

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

于 2008-10-05T16:52:42.247 回答
8

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

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

于 2008-10-05T15:18:03.997 回答
6
  • 遵循保留和释放规则(或使用垃圾收集)。他们总结在这里

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

于 2008-10-05T15:17:55.430 回答
2

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

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

于 2008-10-05T16:20:01.953 回答
1

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

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

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

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

于 2008-10-06T17:39:33.740 回答
1

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

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

于 2008-12-25T20:04:39.403 回答
0

显然,您首先需要了解基本的内存管理概念。但在追查泄漏方面,我强烈建议阅读本教程,了解如何在 Instruments 中使用 Leaks 模式

于 2012-03-22T14:32:28.877 回答