web-dev-qa-db-ja.com

iOS自動解放プールブロック

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

 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を少しの間脇に置いておきたいと思います。

17
Teo

自動解放は、オブジェクトから保持カウントを削除するだけで、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 

}
30
Kibitz503

(ほとんどの場合、いくつかの追加の背景を提供するだけです。@ 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を少しの間脇に置いておきたいと思います。

OK、ARCについては考えないでください。上記では、ARCがないと、objの割り当てが解除されません。 ARCが追加のrelease呼び出しを追加するという理由だけで、おそらく割り当てが解除されます(例を考えると、use the objectで何が起こるかわからないため、実際にはわかりません)。

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

しかし、上記がブロック内にあるかどうかにかかわらず、ARCがなければリークです。

6
Rob Napier

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

1
anivader