如果您尝试释放已释放的对象会发生什么?

时间:2011-05-29 15:38:03

标签: iphone objective-c memory-management

如果我有一个对象怎么办,比如NSIndexPath,在我复制之前我总是首先发布它?

内存数是否可以低于0? 我这样做是为了防止内存泄漏..这是一个好方法吗?

// global在此之前已经有了一些值,或者它没有值..我想更新
 //这带有一个新值(我不再关心旧指针)

 [global release]
 global = [indexPath copy];

2 个答案:

答案 0 :(得分:8)

别。当保留计数达到0时,您的对象将被释放并且其指针将变为无效,因此再次使用它将导致不可预测的结果(即崩溃)。

您应该阅读Apple的Memory Management Guide

这是基本规则:

  • 您只释放或自动释放您拥有的对象。如果使用名称以“alloc”,“new”,“copy”或“mutableCopy”(例如,alloc,newObject或mutableCopy)开头的方法创建对象,或者如果发送它,则获取对象的所有权保留信息。
  • 您使用release或autorelease放弃对象的所有权。 autorelease只是意味着“将来发送一条发布消息”(特别是:当使用的自动释放池收到一条排放消息时)。

<强>更新

正如Josh所指出的,你需要考虑的一个案例是global和indexPath是相同的。在这种情况下,您仍然“需要”指针(执行复制),因此您要么自动释放(而不是释放),要么使用临时变量来处理它。

答案 1 :(得分:0)

您所做的事情基本上是正确的,只要global具有您不再需要的旧值或nil。如果它是类的ivars之一,则在创建类的实例时它将为nil。唯一的问题是,如果新的indexPath碰巧与global中已经存在的对象相同,那么您将会过度释放并且会崩溃。

// global points to object at 0x8BADFOOD
// indexPath also happens to be 0x8BADFOOD; for some reason, it
// hasn't changed since last time. This _can_ happen.
[global release];    // object at 0x8BADFOOD is deallocated
global = [indexPath copy];    // indexPath no longer valid! 
                              // Crash! Bang! Boom!

避免这种情况的方法是使用临时变量。

当您将属性声明为copy并合成该属性时,创建的setter方法看起来与此类似,您可以执行相同的操作:

- (void)setMyFloozit:(Floozit *)newFloozit {
    // Copy first in case newFloozit and myFloozit are for
    // some reason the same object
    // Take ownership of a copy of newFloozit
    Floozit * tmp = [newFloozit copy];
    // We no longer need old value of myFloozit, so we release it.
    [myFloozit release]; 
    // tmp contains a value that we own, we just need to assign
    // it to the correct name.
    myFloozit = tmp;
}

通过首先检查newFloozitmyFloozit是否相同,如果它们无效,可以稍微改善一点。