【问题标题】:Objective-C autorelease pool not releasing objectObjective-C 自动释放池不释放对象
【发布时间】:2010-05-07 12:27:14
【问题描述】:

我对 Objective-C 非常陌生,并且正在阅读内存管理。我试图用 NSAutoreleasePool 玩一下,但不知何故它不会释放我的对象。

我有一个带有 setter 和 getter 的类,它基本上设置了一个 NSString *name。释放池后,我尝试 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;
}

【问题讨论】:

    标签: objective-c autorelease nsautoreleasepool


    【解决方案1】:

    当您释放指针变量时,您是在告诉操作系统它指向的内存可以重新分配。指针仍然指向该内存,并且在重新分配之前它仍然包含对象的剩余部分。一旦它被重新分配,尝试调用 name 方法将不再有效。

    【讨论】:

    • 对。 OP 可能还想研究设置 NSZombieEnabled 以检测访问已释放对象的尝试并立即崩溃。
    • 同意。它的工作纯粹是靠运气,因为 var 指向的内存块仍然包含对象的内容。
    • 这回答了直接问题,但也请注意@Dirks 对其他问题的回答
    • NSZombieEnabled 对于像我这样的初学者来说是件好事......就像大卫所说的那样,当试图访问一个已释放的对象时它会崩溃......谢谢大家
    【解决方案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 的引用)。

    【讨论】:

    • 您可以安全地将 release 发送到 nil,因此您的名称不是 nil 的测试是不必要的。
    • 非常感谢您的回答...这正是发生的事情。释放池后,我尝试使用 TestClass *var1 = [TestClass new]; 创建一个新对象[var name] 的 NSLog 为 NULL....当我为 var1 [var1 setName=@"John"] 设置名称时,我实际上能够通过旧对象 "var" 访问 "John" .... 所以[var name] 实际上打印了“John”...如果 NSZombieEnabled 设置为 YES,它会崩溃。这是完美的经验教训。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多