保留计数&复制在塞特?

时间:2009-10-01 08:32:43

标签: objective-c cocoa

这是前一个问题的后续问题,希望有点清楚。我只是好奇下面的代码如何工作,特别是变量myString被释放。它看起来不像输出?

CODE

// IMPLEMENT
@implementation CelestialBody
- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [newName copy];
    }
}
- (void)dealloc{
    [name release];
    name = nil;
    [super dealloc];
}
@end

// ------------------------------------------------------------------- **
// MAIN: 30th September 2009
// ------------------------------------------------------------------- **

#import <Foundation/Foundation.h>
#import "CelestialBody.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    CelestialBody *newPlanet = [[CelestialBody alloc] init];
    NSString *myString = [[NSString alloc]initWithFormat:@"go home"];
    NSLog(@"RetainCount_1: %d",[myString retainCount]);

    [newPlanet setName: myString];
    NSLog(@"RetainCount_2: Incremented by copy in setName");    

    // Clean up
    NSLog(@"RetainCount_2: %d -Before Release",[myString retainCount]);
    [newPlanet release];
    [myString release];
    [pool drain];
    NSLog(@"RetainCount_1: %d -After Release",[myString retainCount]);
    return 0;
}
// ------------------------------------------------------------------- **

输出

Running…
2009-10-01 09:28:50.395 RetainCount_1: 1
2009-10-01 09:28:50.399 RetainCount_2: Incremented by copy in setName
2009-10-01 09:28:50.399 RetainCount_2: 2 -Before Release
2009-10-01 09:28:50.400 RetainCount_1: 1 -After Release
Debugger stopped.

我目前正在重读“记忆管理指南”,试着看看我错过了什么。

非常感谢

修改

刚刚向dealloc添加了一个版本,看起来这就是我所缺少的。

- (void)dealloc{
    [name release];
    name = nil;
    [super dealloc];
}

加里

3 个答案:

答案 0 :(得分:3)

  

是变量myString被释放。

[myString release];

所有迹象都表明是。

  

它看起来不像输出?

NSLog(@"RetainCount_2: %d",[myString retainCount]);
[myString release];

您的NSLog语句的输出未反映release消息,因为release消息尚未发生。

另外,不要担心保留计数。它们可能会产生误导。只要您遵循Cocoa的规则并且不创建任何所有权周期(A拥有B拥有C拥有A),您就很少遇到问题。

答案 1 :(得分:2)

这不是你的问题的答案本身,而是对你所看到的内容的解释:对retainCount的最后一次调用被发送到一个解除分配的对象,这是未定义的行为。该对象恰好还没有被覆盖,所以它仍然有点“工作”,因为方法调度仍然可以看到那里的旧数据并且没有意识到它是无效的。你永远不会从调用retainCount回来0,因为这样的对象不可能存在。

答案 2 :(得分:1)

我猜[newName copy]实际上并没有复制NSString,因为NSString是不可变的?我从来没有想过这个,但这对我来说很有意义。

在程序结束时,您将发布newPlanet和myString。我的问题是,您是否在CelestialBody的-dealloc方法中发布了实例变量名称?如果你不是,那么我相信你在那里泄漏记忆。

  1. 创建myString:NSString的retainCount为1
  2. [newPlanet setName:]:NSString的retainCount为2
  3. [newPlanet release]:NSString的retainCount是2?我想你不是在-dealloc中发布它。
  4. [myString release]:NSString的retainCount为1