17

プールブロックを自動解放するようになったとき、メモリ管理に関するAppleのドキュメントを読んでいて、何か考えさせられました。

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

これを完全に理解しているかどうかはわかりません。自動解放プール ブロック内で作成されたオブジェクトは、いずれにせよブロックの最後に解放されます。それが寿命だからです。オブジェクトがブロックの最後に到達したときにオブジェクトが解放されるのに、なぜオブジェクトに 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?!
  }

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 は考慮しません。上記では、ARCobjがないと、割り当てが解除されません。ARCが追加のrelease呼び出しを追加するためだけに、割り当てが解除される可能性があります(あなたの例では、で何が起こるかわからないため、実際にはわかりませんuse the object)。

@ Kibitz503 が説明しているように、「解放」は「割り当て解除」を意味するものではありません。ブロックの最後に、自動解放プールがドレインされます。つまり、保留中のautorelease呼び出しはreleaseブロックの最後に送信されます。その結果、オブジェクトの保持カウントが 0 に達すると、割り当てが解除されます。

しかし、上記がブロックにあるかどうかに関係なく、ARCがないとリークです。

于 2013-04-24T18:00:09.413 に答える
1

自動解放プールは、プールの最後までオブジェクトの解放を延期します。これにより、オブジェクトが最後に到達する前に解放される可能性が回避されます。つまり、基本的には、プールの終了前にオブジェクトが解放されないようにすることです。

于 2014-12-19T07:28:19.093 に答える