25

我是内存管理代码的新手,但我很好地理解了这个想法。

在通过 XCode 中的泄漏工具获取我的应用程序时,我注意到我只需要清理我的自定义对象,而不是例如动态创建的数组,所以我认为这些数据类型是自动释放的——因为我只需要释放数组我用作对它们有(保留)的属性。

然后我注意到一些奇怪的事情:我在某个初始化的数组上出现了泄漏,如下所示:

NSMutableArray *removals = [NSMutableArray new];

但不是类似的

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:9];

现在,一个设置为“新”的原因是它可以有 0-99 个项目,而我知道的另一个总是 9。由于两个数组稍后根据用户传递给相同的方法交互时,如果我没有在方法结束时释放,或者如果我释放了异常,我会得到泄漏!

我将第一个数组更改为

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];

我没有泄漏,也不必释放任何东西。谁能解释一下?

4

3 回答 3

65

正如内存管理规则中所述,只要您拥有使用+alloc+new-copy或创建的对象,您就-mutableCopy拥有它并负责在某个时候释放它。(实际上,+new只是 . 的简写[[MyClass alloc] init]。)正如您所指出的,通过创建数组[NSArray new]而不释放它是内存泄漏。但是,如果您正确处理此对象,通常可以在某个时候释放它。例如:

  • 如果从创建数组方法中调用使用数组的方法,那么您应该能够在使用后释放数组。如果内部方法需要对周围的数组保持更永久的引用,则该方法负责发送并最终发送给对象。例如:-retain-release

    - (void)myMethod {
        NSArray *removals = [NSArray new];
        // ...
        [someObject someOtherMethod:removals];
        [removals release];
    }
    
  • -init如果您在对象的方法中创建了数组,则该-dealloc方法可以在对象被销毁时释放它。

  • 如果您需要创建数组然后从方法中返回它,您已经发现了自动释放被发明的原因。方法的调用者不负责释放对象,因为它不是+alloc+new-copy-mutableCopy方法,但您需要确保最终释放它。-autorelease在这种情况下,您在返回之前手动调用该对象。例如:

    - (NSArray *)myMethod {
        NSArray *removals = [NSArray new];
        // ...
        return [removals autorelease];
    }
    

当您通过 创建数组时+arrayWithCapacity:,您不会调用“特殊”方法之一,因此您不必释放结果。这可能是用 实现的-autorelease,很像上面的最后一个例子,但不一定。(顺便说一句,你也可以用 ; 创建一个空的自动释放的 NSMutableArray,[NSMutableArray array]该方法在 NSArray 中找到,因此它不会出现在 NSMutableArray 下的文档中,但它会在发送到 NSMutableArray 类时创建一个可变数组。)如果你' 将从你的方法中返回数组,你可以使用它作为简写[[[NSMutableArray alloc] init] autorelease]——但这只是一个快捷方式。-init但是,在许多情况下,您可以使用或创建一个对象,+new并在适当的时候手动释放它。

于 2009-08-02T21:20:03.790 回答
7

这就是幕后实现的方式:

+(NSMutableArray*) new
{
    return [[NSMutableArray alloc] init];
}

+(NSMutableArray*) arrayWithCapacity:(NSNumber)capacity
{
    return [[NSMutableArray alloc] initWithCapacity:capacity] **autorelease**];
}

在第一种情况下,仅分配数组,您负责取消分配它。相反,arrayWithCapacity 已为您自动释放,即使您忘记释放也不会导致泄漏。

于 2011-04-22T09:35:53.840 回答
4

Cocoa 使用某些命名约定。任何以 alloc、new 或 copy 开头的内容都会返回 retainCount 为 1 的内容,并且您需要释放。函数返回的任何其他内容都有一个平衡的 retainCount(它可能被其他东西持有,或者它可能被保留并被释放)。

所以:

NSMutableArray *removals = [NSMutableArray new];

保留计数为 1,并且:

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99];

或者

NSMutableArray *removals = [NSMutableArray array];

不要因为方法没有以 alloc、new 或 copy 为前缀。这在内存管理文档中都有详细说明。尤其:

如果您使用名称以“alloc”或“new”开头或包含“copy”(例如,alloc、newObject 或 mutableCopy)的方法创建对象,或者向其发送保留消息,则您将获得对象的所有权。您有责任放弃使用 release 或 autorelease 拥有的对象的所有权。任何其他时间您收到一个对象,您都不能释放它。

于 2009-08-02T19:21:14.607 回答