2010-06-21 41 views
2

我担心我很愚蠢。目标C自我变量与变量赋值之间的差异

我已经花了大约三个小时追踪内存泄漏,这已经破坏了我的理智,并且在评论了我的一半应用后,我得出了以下结论。

鉴于以下在正确的地方。

NSString *blah; 

@property (nonatomic, retain) NSString *blah; 

@synthesize blah; 

-(id)initWithBlah:(NSString*)b { 

    self.blah = b; //this leaks 
    blah = b;   //this does not 

} 

我不是特别有经验的objectice c,我明白,如果我在调用object.blah = b;我会透明地调用一个保留b的setter函数。在函数内部,我假定通过将它设置为self.blah = b我由于某种原因双重保留?

有人可以向我解释为什么会出现这种情况,或者如果不是我可能做错了什么?

干杯

回答

2
blah = b 

直接修改类的实例变量。

self.blah = b 

将调用访问器(如果存在) - 从而保留,根据需要释放资源。

您应该将[blah release];添加到您的dealloc方法中,以便在您的课程发布时释放资源。

2

你错了。 blah = b;分配没什么意义,因为在您的代码从initWithBlah:返回后,您不能再依赖字符串。每当你访问它时,它很可能已经被释放。

self.blah = b;赋值是正确的,因为它调用setter并从而取得该字符串的所有权。当然,您也必须在您的-dealloc中发布blah,以防止内存泄漏。

+0

啊谢谢。由于某种原因,我假设因为setter透明地执行了保留,即某段代码会记住它的存在,并在销毁时透明地释放它。谢谢你解决我的问题。 – dageshi 2010-06-21 21:50:20

+2

顺便说一下,惯例是对'NSString *'变量使用'@property(nonatomic,copy)'而不是'(nonatomic,retain)'。通过保留,另一个对象可以将一个可变字符串分配给您的属性,然后修改字符串的内容,而不会让您的类发现它,这会破坏封装。 – 2010-06-21 21:55:39

0

使用访问器是好的,如果它泄漏,那么其他东西是错误的。

尤其是你的初始化器必须被正确调用,即遵循Cocoa内存管理的指导原则,即参数不被被调用者隐式拥有。

所以下面的,因为它通过在自动释放字符串就可以了:

YourObj *obj = [[YourObj alloc] initWithBlah:[NSString stringWithString:@"blah"]]; 

虽然由于传递一个保留字符串以下泄漏:

YourObj *obj = [[YourObj alloc] initWithBlah:[[NSString alloc] initWithString:@"blah"]]; 

你必须要另一件事意识到是宣布的属性不会自动处理清理,所以一定要处理在-dealloc

- (void)dealloc { 
    self.blah = nil; 
    // ... 
} 
1

如果你只给予等值,它不会为字符串分配,如果你给self.blah,它会尝试启动自己并为自我类分配,并尝试分配给你尝试访问的变量,所以你必须释放它或在dealloc方法中使blah = nil。

- (void)dealloc 

{ 

    self.blah = nil; 

     or 

    [self.blah release]; 

}