我是Objective-C的新手,正在阅读内存管理。我试图用NSAutoreleasePool玩一下但不知何故它不会释放我的物体。
我有一个带有setter和getter的类,它基本上设置了一个NSString *名称。在释放游泳池之后,我尝试了NSLog对象并且它仍然有效,但我想它不应该?
@interface TestClass : NSObject
{
NSString *name;
}
- (void) setName: (NSString *) string;
- (NSString *) name;
@end
@implementation TestClass
- (void) setName: (NSString *) string
{
name = string;
}
- (NSString *) name
{
return name;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
TestClass *var = [[TestClass alloc] init];
[var setName:@"Chris"];
[var autorelease];
[pool release];
// This should not be possible?
NSLog(@"%@",[var name]);
return 0;
}
答案 0 :(得分:5)
当您释放指针var时,您告诉操作系统它指向的内存可以重新分配。指针仍然指向该内存,直到它被重新分配,它仍然包含您的对象的遗骸。一旦重新分配,尝试调用name方法将不再有效。
答案 1 :(得分:2)
您的代码有几个问题。首先,您不会copy
也不会retain
存储在name
实例变量中的字符串。因此,如果字符串由将其存储到属性中的任何人释放,则会留下悬空引用。你应该做
- (void) setName: (NSString*) aName {
if( name != aName ) {
if( name ) [name release];
name = [aName retain]; // or copy
}
}
或从一开始就使用属性。
此外,如果在实例变量中保留对象引用,则应提供dealloc
方法的正确定义:
- (void) dealloc {
self.name = nil;
[super dealloc];
}
最后,仅仅因为对象已被释放,并不意味着前一个实例的内存无效。你的原始程序最有可能在一个悬空引用(var
)上调用一个方法,这恰好可以在这里运气。 (特别是,(auto
)release
不会自动将引用设置为nil
)。