17

I was reading the documentation from apple about memory management when I got to autorelease pool blocks and something got me thinking.

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

I am not sure I fully understand this. Any object created inside an autorelease pool block gets released at the end of the block anyway because that is it's life span. Why would you need to call autorelease to the object when it is going to get released anyway when it reaches the end of the block?

To be clearer, I will give an example, of what I am thinking:

   @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: Please don't tell me that because of ARC we don't need to do some things because ARC takes care of them. I am fully aware of that, but I want to leave ARC aside for just a few moments to understand the mechanism of memory management.

Imran
  • 1,715
  • 2
  • 20
  • 42
Teo
  • 3,394
  • 11
  • 43
  • 73

3 Answers3

31

Autorelease just removes a retain count from the object it does not "free" the memory immediately like in c. When the autorelease pool ends all auto released objects with a count of 0 will have their memory freed up.

Sometimes you create a lot of objects. An example would be a loop that is creating new strings every time it iterates and adds new data to the string. You may not need the previous versions of the string and will want to free up memory used by those. You can accomplish this by explicitly using the autorelease pool instead of waiting for it to be done naturally.

//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
  • 867
  • 6
  • 10
  • 1
    so how is this answering my question? I provided a simple example only to avoid answers like this that don't have much to do with the question. I also added comments to the small example. – Teo Apr 24 '13 at 17:41
  • 1
    Typically you only use autorelease pools in a function where there is high memory usage and you need it freed sooner then normal. The paragraph was intended to add context. – Kibitz503 Apr 24 '13 at 17:47
  • Ok, so on a non ARC env, `` MyObject *obj = [[MyObject alloc] init];`` inside an autorelease pool would be a memory leak but on an ARC env, the compiler adds automatically a release call for the object or why it isn't a memory leak anymore? – Teo Apr 24 '13 at 17:59
  • 1
    Exactly, The strong pointer was on the function level so once the function exits there are no strong pointers so the object is freed. If there was a strong pointer in the class that pointed to it it would not be freed because the class still exists and therefore it has a strong pointer still. In ARC the compiler adds autorelease for you! – Kibitz503 Apr 24 '13 at 18:02
  • +1, thanks for clearing my thoughts and sorry for judging your comment too early. All te best :) – Teo Apr 24 '13 at 18:04
  • No problem glad I could help. This stuff was pretty confusing coming from the c++ world and even more so once ARC was thrown in the mix. – Kibitz503 Apr 24 '13 at 18:05
  • 3
    "Autorelease just removes a retain count from the object it does not "free" the memory immediately like in c." No. `autorelease` simply adds an object to the autorelease pool. "When the autorelease pool ends all auto released objects with a count of 0 will have their memory freed up." No, when the autorelease pool ends it `release`s all objects in the pool. A `release` anywhere (whether by the autorelease pool or elsewhere) may cause the object to be deallocated if the retain count before the `release` was 1. – newacct Apr 24 '13 at 23:24
  • This answer needs to be modified to fix the errors that @newacct mentioned. – kevlar Mar 01 '14 at 20:07
  • I used casual language to express an idea to someone that had already read the documentation and did not understand. Regurgitating the technical explanation didn't seem like the best approach. There is no need to modify the original post. Calling autorelease on an object has the end result of decrementing the retain count on an object. If the retain count reaches 0 the object is deallocated. – Kibitz503 Mar 05 '14 at 23:06
6

(Mostly just giving some additional background; @Kibitz503 is getting you to the right answer.)

@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: Please don't tell me that because of ARC we don't need to do some things because ARC takes care of them. I am fully aware of that, but I want to leave ARC aside for just a few moments to understand the mechanism of memory management.

OK, let's not consider ARC. In the above, without ARC, obj would not be deallocated. Only because ARC adds additional release calls does possibly get deallocated (given your example, we actually have no idea since we don't know what happens in use the object).

As @Kibitz503 explains, "release" does not mean "deallocate." At the end of the block, the autorelease pool drains, which means any pending autorelease calls are sent as release at the end of the block. If that leads to the object reaching a 0 retain count, then it is deallocated.

But whether the above is in a block or not, without ARC it is a leak.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Good clarification about the leak. It is a leak with or without the autorelease pool wrapped around it! – Kibitz503 Apr 24 '13 at 18:07
  • Does this mean that if I use ARC and release an object from somewhere outside the ``@autoreleasepool{}`` the object still exists until the end of the @autoreleasepool block? – Michael Feb 23 '15 at 00:16
  • It depends on the code. At the end of the autoreleasepool block, all pending autoreleases created in that block are sent. I don't know what "release an object" means in your example. You probably want to put together a specific code example and post a new question. – Rob Napier Feb 23 '15 at 04:16
1

Autorelease pools defer release of the object till the end of the pool which avoids the possibility of it being released before it reaches the end. So basically, it is to make sure the object will not be released before the end of the pool.

anivader
  • 364
  • 1
  • 4
  • 17