Objective-C 中的内存管理

Posted

技术标签:

【中文标题】Objective-C 中的内存管理【英文标题】:Memory management in objective-c 【发布时间】:2010-03-11 09:59:27 【问题描述】:

我的一门课中有这段代码:

- (void) processArray


   NSMutableArray* array = [self getArray];
   . . .
   [array release];
   array  = nil;



- (NSMutableArray*) getArray

   //NO 1:
   NSMutableArray* array = [[NSMutableArray alloc]init];

   //NO 2:
   NSMutableArray* array = [NSMutableArray array];
   . . .
   return array;

NO 1:我创建一个数组并返回它。在processArray 方法中我释放它。

NO 2:我只需调用array 即可获得一个数组。因为我不是这个的所有者,所以我不需要在 processArray 方法中释放它。

哪个是最好的选择,NO 1 还是 NO 2?还是有更好的解决方案?

【问题讨论】:

这可能会有所帮助:***.com/questions/1219575/… 【参考方案1】:

该方法应该返回一个自动释放的数组,NO 2 是更好的选择。这样做的原因是,当您使用

调用该方法时
   NSMutableArray* array = [self getArray];

按照惯例,您会期望 不必 必须释放数组。如果你想拥有它,你就保留它,否则你不应该关心它。在 Cocoa 中,您通过显式发送 allocretaincopy(或 new)获得所有权。由于processArray 方法不这样做,它不应该负责释放数组。

所以你应该使用 NO 2,并且你应该删除这两行:

[array release];
array  = nil;

【讨论】:

+1 该约定确实有助于控制内存泄漏和对 nil 的调用。 +1 除此之外,应该使用 Clang 静态分析器(已经内置在 Xcode for Snow Leopard 中)。这将有助于在使用 Build > Build and Analyze 时进行内存管理。一个例子:img682.imageshack.us/img682/2549/clanganalyzerinxcodeisa.png Felixyz,如果我想要这些数组的所有权(在“getArray”中创建),那么我该如何实现呢?你有什么例子吗? @prathumca: NSMutableArray* array = [[self getArray]retain];从 getArray 返回的对象(遵循方法 NO 2)是自动释放的,并将在下一个 runloop 中释放,但是如果您在获取它时立即保留它,您将拥有它的所有权并且它将一直保持活动状态直到您 @987654330 @ 它。这是autorelease 的主要目的之一:能够返回对象并让调用者决定是否要保留它们。【参考方案2】:

如果数组及其内容使用大量内存或多次使用,您会希望立即释放它们,因此使用选项 1。根据 Objective-C 指南,您需要添加前缀在这种情况下,您的子例程名称中的单词“new”而不是“get”。

另一方面,如果您想减少简单地说 [array release]; 的代码行数;或类似的,然后使用选项 2。

这只是减少代码行数和减少不必要的临时内存使用之间的平衡。

虽然自动释放池有助于减少内存泄漏并使代码更小,但有时您需要在所有内容停止使用时显式释放所有内容以减少内存使用。

HTH

编辑

啊 - 我的立场是正确的。 阅读 iPhone version of the Memory Management Programming Guide for Cocoa 我看到 iPhone 指南是使用前缀“new...”,例如在这种情况下使用“newArray”,如果调用者应该手动释放而不是“创建...”的前缀。 “创建”可以指手动释放或自动释放对象的创建,因此是模棱两可的。上面的文字已更正。

【讨论】:

我认为不仅仅是代码行数,更重要的是要严格遵守所有权约定。否则,与内存相关的错误将使在 Objective-C 中编程几乎不可能。 @martinr:你所说的“create”前缀很有趣,也很有意义,尽管它似乎没有在 Cocoa 类中使用。 (有很多名称中带有“Create”的CoreFoundation函数示例。我查阅了相关文档,但找不到任何提及“create”方法的内容:developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…您能指出您提到的文档吗?跨度> @martinr(编辑后):好的,这个约定很好了解。我只能在 NSAtomicStore 上的实际 iPhone API(newReferenceObjectForManagedObject: 和 newCacheNodeForManagedObject:) 中找到它的两个使用示例,我想这与该类的“工厂”字符有关(但没有使用所以我不确定这是不是真的)。​​【参考方案3】:
- (void) processArray


   NSMutableArray* array = [[self getArray] retain];
   //Now you are the owner of array, so you take care to release it

   . . .

   [array release];
   array  = nil;



- (NSMutableArray*) getArray

   //create a new array 
   //temporarily the method owns the array
   NSMutableArray* array = [[NSMutableArray alloc]init];

   //fill in here with elements or what you want
   ..........

   [array autorelease];
   //autorelease here says "I don't own the result
   //if anyone cares about it, he should retain it himself

   return array;

简而言之,当您创建新对象时,您应该在返回之前自动释放它们。 因为如果调用方法想要使用结果,调用方法应该小心 保留和释放结果。

当您不确定您的保留/释放代码时,最好为这个问题运行 Klang 静态分析器:http://clang-analyzer.llvm.org/

【讨论】:

以上是关于Objective-C 中的内存管理的主要内容,如果未能解决你的问题,请参考以下文章

读书笔记系列—Objective-C中的内存管理

Objective-C 中的内存管理

Objective-C 中的内存管理

Objective-C 的内存管理帮助

iOS开发系列—Objective-C之内存管理

iOS开发系列—Objective-C之内存管理