【问题标题】:Does this Objective-C code leak memory?这个 Objective-C 代码会泄漏内存吗?
【发布时间】:2011-03-29 22:24:55
【问题描述】:

我担心的一件事是我创建了两个整数,但不释放它们。将它们设为 NSInteger 会更好吗?

-(void) flipCoin {

    int heads = [headsLabel.text intValue];
    int tails = [tailsLabel.text intValue];

    if (random() %2 ==1 )
    {
        heads++;
    }
    else {
        tails++;
    }

    headsLabel.text = [NSString stringWithFormat:@"%d", heads] ;
    tailsLabel.text = [NSString stringWithFormat:@"%d", tails];

}

【问题讨论】:

    标签: objective-c cocoa cocoa-touch memory-leaks


    【解决方案1】:

    没有。您的 headstails 变量是本地的并存储在堆栈中。这不会导致泄漏。您在底部附近的两个 NSString 分配是使用便利构造函数创建的,并将为您自动释放。

    【讨论】:

      【解决方案2】:

      所有默认数据类型(intcharBOOL 等)都会自动为您管理,并且不会(也不能)被释放(出于所有意图和目的)。 NSIntegers 的行为类似,因为它们只是 signed ints(或 signed longs 在 64 位机器上)。

      但是,您初始化的对象,例如 NSStringNSArray 通常必须被释放(除非它们是自动释放的,例如代码底部的 NSStrings)。如果您曾经在某事上致电-alloc-init,您将不得不稍后发布它。如果你怀疑一个方法是否返回一个自动释放的对象,只需阅读文档(它会告诉你)。

      另外,如果您想了解内存管理,有很多很棒的资源可以教您(Google 是一个很好的起点!),如果您认为您的代码会泄漏内存,请运行它乐器,你就能分辨出来……

      【讨论】:

        【解决方案3】:

        正如 sha 所指出的,局部变量在当前堆栈帧中分配。一旦当前函数调用返回,堆栈就会“弹出”,并且为当前调用占用的内存不会被释放,而是被放弃,直到它被下一个被压入堆栈部分的调用覆盖。

        那么为什么我们必须像这样释放变量:

        MyClass *myObject = [[MyClass alloc] init];
        

        好吧,您实际上不必担心“myObject”。它在堆栈上,就像你的整数一样,当当前调用完成时它会被清理。

        您需要担心的是 myObject(它是一个指针)指向的内存。它在堆上的某个地方。构造一个对象需要向运行时请求一些半永久性的地方来放置它;该进程返回一个内存地址,您的指针存储该地址。

        allocrelease 是 Objective-C 的习惯用法,它们在很大程度上取代了 C 的 malloc()free() 函数,但它们最终都要求计算机在堆上留出内存,以及所有这些内存最终必须通过自动释放池、release 消息或free() 调用返回。

        【讨论】:

        • +1 表示这句话:“好吧,你实际上不必担心“myObject”。它在堆栈上,就像你的 int 一样,它会在当前调用时被清理结束。”。这个事实很重要,因为很多没有经验的人不明白。
        • 另一件值得指出的事情:int 和其他原始类型的值不是 Cocoa 或 CF 对象,这就是为什么(1)您不像处理 Cocoa 和 CF 对象那样管理它们(它们没有保留计数),(2)您根本不能向它们发送任何消息,以及(3)您不能将它们直接放入任何 Cocoa 或 CF 集合对象中;您必须将它们包装在值对象中,例如 NS/CFNumber 或 NS/CFString 并将它们放入您的集合中。 NSInteger、NSUInteger、CFIndex 和 CGFloat 只是原始类型的其他名称(typedef),所以它们也都是如此。
        • 如果您在函数调用中使用 alloc init 创建对象,您必须在该函数调用中释放它还是会像局部变量一样自动处理它?
        • @awakeFromNib:您必须在对象超出范围之前释放它。这就是为什么答案有点误导。您不会释放整数,因为它们是局部变量,而是因为它们不是 Objective-C 对象。
        • 局部变量自动处理。指向您的对象的指针是一个局部变量。会自动处理的。它指向的对象不是本地的,必须释放。
        【解决方案4】:

        int 是所谓的原始类型。它不是一个指向 Objective-C 对象的指针,所以你不能释放它。你甚至不能给它发消息。

        NSInteger 也是原始类型,因为它是原始类型的 typedef(通常为 long)。所以你也不能释放它。

        你需要发布什么?您需要释放您通过发送 new、alloc 或包含副本的方法获得的任何对象。您还需要释放已发送保留的对象。所以下面所有的局部变量都必须释放:

        -(void) foo
        {
            NSString* aString  = [[NSString alloc] init];
            NSString* aString2 = [aString copy];
            NSString* aString3 = [someOtherString retain];
            NSString* aString4 = [@"some string" copy];
        }
        

        注意,由于实施细节,您实际上可以不发布 aString4 而侥幸,但您不必担心。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-19
          • 2016-08-27
          • 1970-01-01
          相关资源
          最近更新 更多