17

当我要自动释放池块时,我正在阅读苹果关于内存管理的文档,这让我开始思考。

 Any object sent an autorelease message inside the autorelease pool block is  
 released at the end of the block.

我不确定我是否完全理解这一点。无论如何,在自动释放池块中创建的任何对象都会在块的末尾释放,因为那是它的生命周期。当对象到达块的末尾时无论如何都会被释放,为什么你需要调用自动释放对象呢?

为了更清楚,我将举例说明我的想法:

   @autoreleasepool {

    MyObject *obj = [[MyObject alloc] init]; // no autorelease call here

    /* use the object*/
   //....
   // in the end it should get deallocated because it's lifespan ends, right?
   // so why do we need to call autorelease then?!
  }

PS:请不要告诉我因为ARC我们不需要做一些事情,因为ARC会照顾它们。我完全意识到这一点,但我想暂时将 ARC 放在一边,以了解内存管理的机制。

4

3 回答 3

30

Autorelease 只是从对象中删除一个保留计数,它不会像在 c 中那样立即“释放”内存。当自动释放池结束时,所有计数为 0 的自动释放对象都将释放其内存。

有时你会创建很多对象。一个例子是一个循环,它每次迭代并将新数据添加到字符串时都会创建新字符串。您可能不需要以前版本的字符串,并希望释放那些使用的内存。您可以通过显式使用自动释放池来完成此操作,而不是等待它自然完成。

//Note: answers are psudocode

//Non Arc Env
@autoreleasepool 
{

    MyObject *obj = [[MyObject alloc] init]; // no autorelease call here
    //Since MyObject is never released its a leak even when the pool exits

}
//Non Arc Env
@autoreleasepool 
{

    MyObject *obj = [[[MyObject alloc] init] autorelease]; 
    //Memory is freed once the block ends

}
// Arc Env
@autoreleasepool 
{

    MyObject *obj = [[MyObject alloc] init]; 
    //No need to do anything once the obj variable is out of scope there are no strong pointers so the memory will free

}

// Arc Env
MyObject *obj //strong pointer from elsewhere in scope
@autoreleasepool 
{

    obj = [[MyObject alloc] init]; 
    //Not freed still has a strong pointer 

}
于 2013-04-24T17:38:58.660 回答
6

(主要只是提供一些额外的背景知识;@ Kibitz503 让您找到正确的答案。)

@autoreleasepool {

  MyObject *obj = [[MyObject alloc] init]; // no autorelease call here

  /* use the object*/
  //....
  // in the end it should get deallocated because it's lifespan ends, right?
  // so why do we need to call autorelease then?!
}

PS:请不要告诉我因为ARC我们不需要做一些事情,因为ARC会照顾它们。我完全意识到这一点,但我想暂时将 ARC 放在一边,以了解内存管理的机制。

好的,我们不考虑ARC。在上面,如果没有 ARC,obj就不会被释放。只是因为 ARC 添加了额外的release调用,才可能被释放(以您的示例为例,我们实际上不知道,因为我们不知道 中发生了什么use the object)。

正如@Kibitz503 解释的那样,“释放”并不意味着“解除分配”。在块结束时,自动释放池耗尽,这意味着任何挂起autorelease的调用都将release在块结束时发送。如果这导致对象达到 0 保留计数,则将其释放。

但是无论上面是否在一个块中,没有 ARC 都是泄漏。

于 2013-04-24T18:00:09.413 回答
1

自动释放池将对象的释放推迟到池的末尾,这避免了它在到达末尾之前被释放的可能性。所以基本上,就是要确保对象在池结束之前不会被释放。

于 2014-12-19T07:28:19.093 回答