我尝试更好地理解Objective C中的内存管理(没有ARC)。 目前正在创建一个简单的程序来试用它。
我的代码
...
//create some object
RetainTracker * rt = [RetainTracker new]; //RC=1
NSLog(@"Just created - %lu", (unsigned long)[rt retainCount]);
[rt retain]; // RC=2
NSLog(@"%lu", (unsigned long)[rt retainCount]);
[rt release]; //RC=1
NSLog(@"%lu", (unsigned long)[rt retainCount]);
[rt release]; //RC=0 -> call to dealloc
//call to object rt again after it was deallocated and get RC=1
NSLog(@"%lu", (unsigned long)[rt retainCount]); //think that here must be exception ?
结果:
因此,结果我们可以看到在我发布最后一个引用和对象rt之后引用计数器仍然等于1。
我更深入,并与仪器“生命”调查此对象,下一步
据我所知:
[rt retain]
- RC = 2; [rt release]
- RC = 1; [rt release]
- RC = 0; 所以,对象必须被释放,但是如果我在步骤4之后调用[rt retainCount]
,那么此对象的RC仍然等于1.为什么?也许我犯错了或错过了什么?
答案 0 :(得分:3)
取消分配对象后,使用指向对象的指针会导致未定义的行为。也就是说,它可以打印1,42,你的程序可能会崩溃,Hello Kitty可能会弹出你的计算机;什么都可能发生。任何行为都与未定义的行为一致,即使是表明正在发生其他事情的行为也是如此。
除了它未定义的行为之外,你所看到的很可能是基于你所做的。取消分配对象后,其内存将标记为可供使用,但构成内存中对象的字节仍保留在那里。因此,在很长一段时间内,很可能它没有被其他东西覆盖,而且内存仍然会看起来"就像被解除分配的对象一样,向它发送消息(虽然未定义的行为)可能会成功,因为它只是使用对象的部分仍然在内存中的正确位置。
关于保留计数,你假设当你release
时,保留计数(但它存储在内存中)总是递减,所以如果在release
之前它是1,之后应该是0.但是,当保留计数为1时,他们不必这样做,因为他们知道当你release
保留计数为1的对象时,对象将是取消分配,之后你不应该使用该对象,所以他们也可以在这种情况下跳过减少它,因为更新一个不再使用的变量没有意义。
答案 1 :(得分:0)
当池的保留计数为0时,对象将被释放。对象在释放后仍可能在内存中。尝试在下一次排水后访问它,看看会发生什么。
更新: 是。我的错。出于某种原因,我错过了它没有自动释放的事实。但是我正在查看retainCount方法,并在文档中找到了这个:"不要使用此方法。 (必需)"
并遵循:" ...您不太可能从此方法中获得有用的信息"。
似乎retainCount方法可能无法可靠地为您提供对象的保留计数。但是,仍然很奇怪你甚至可以将该消息发送到应该被释放的那个对象。