iOS自动释放池块

iOS自动释放池块,ios,memory-management,objective-c-blocks,autorelease,nsautoreleasepool,Ios,Memory Management,Objective C Blocks,Autorelease,Nsautoreleasepool,当我进入自动释放池块时,我正在阅读苹果关于内存管理的文档,有件事让我思考 Any object sent an autorelease message inside the autorelease pool block is released at the end of the block. 我不确定我是否完全理解这一点。在自动释放池块中创建的任何对象都会在块的末尾释放,因为这是它的生命周期。当对象到达块的末尾时仍将被释放时,为什么需要调用对象的自动释放 为了更清楚,我将举一个例子,说

当我进入自动释放池块时,我正在阅读苹果关于内存管理的文档,有件事让我思考

 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暂时搁置一下,以了解内存管理的机制。

自动释放只是从对象中删除一个保留计数,它不会像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 

}
(大部分只是提供一些额外的背景;@Kibitz503会让你找到正确的答案。)

PS:请不要告诉我,因为ARC,我们不需要做一些事情,因为ARC会照顾他们。我完全明白这一点,但我想把ARC放在一边,让我们先了解一下内存管理的机制

请不要考虑ARC。在上述情况下,如果没有ARC,
obj
将不会被解除分配。仅因为ARC添加了额外的
release
调用才可能被解除分配(根据您的示例,我们实际上不知道,因为我们不知道
使用对象时会发生什么情况)

正如@Kibitz503所解释的,“release”并不意味着“deallocate”。在块的末尾,自动释放池将耗尽,这意味着任何挂起的
autorelease
调用都将在块的末尾作为
release
发送。如果这导致对象达到0保留计数,那么它将被释放


但是,无论上面是否在一个块中,如果没有弧,则是泄漏

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

这是如何回答我的问题的?我提供了一个简单的例子,只是为了避免回答与问题无关的问题。我还为这个小示例添加了注释。通常,在内存使用率较高的函数中,您只需要使用自动释放池,并且需要在正常情况下更早地释放它。这一段是为了添加上下文。好吧,在非弧环境中,`MyObject*obj=[[MyObject alloc]init];`在自动释放池中可能会出现内存泄漏,但在ARC env上,编译器会自动添加对象的释放调用,或者为什么它不再是内存泄漏?确切地说,强指针位于函数级别,因此一旦函数退出,就没有强指针,因此对象被释放。如果类中有一个指向它的强指针,它将不会被释放,因为类仍然存在,因此它仍然有一个强指针。在ARC中,编译器为您添加自动释放!“Autorelease只是从对象中删除一个保留计数,它不会像c中那样立即“释放”内存。“No.
Autorelease
只是将一个对象添加到Autorelease池中。“当自动释放池结束时,所有计数为0的自动释放对象将释放其内存。”否,当自动释放池结束时,将释放池中的所有对象。如果
释放之前的保留计数为1,则
释放
任何地方(无论是通过自动释放池还是其他地方)都可能导致对象被释放。关于泄漏的详细说明。无论是否有自动释放池环绕,这都是一个漏洞!这是否意味着如果我使用ARC并从
@autoreleasepool{}
之外的某个地方释放一个对象,该对象在@autoreleasepool块结束之前仍然存在?这取决于代码。在autoreleasepool块的末尾,将发送在该块中创建的所有挂起的autorelease。我不知道在你的例子中“释放一个对象”是什么意思。您可能想要组合一个特定的代码示例并发布一个新问题。
@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?!
}