LoginSignup
1
0

More than 5 years have passed since last update.

Objective-Cでヒープ上にないオブジェクトについて

Last updated at Posted at 2017-08-19

Objective-C(2.0)において、オブジェクトは必ずしもヒープ上にないらしいので、少し調べた。

ブロックオブジェクト

ブロックはヒープ上にあるときとないときがある。
ブロックを作ると、その情報はブロックオブジェクトが保持する。
ブロックオブジェクトのクラスには、

  • 何もキャプチャしない __NSGlobalBlock__ (_NSConcreteGlobalBlock)
  • 情報をスタック上に持つ __NSStackBlock__ (_NSConcreteStackBlock)
  • 情報をヒープに持つ __NSMallocBlock__ (_NSConcreteMallocBlock)

の3種類がある。ブロックオブジェクトもObjective-Cのオブジェクトであり、Block_private.hにレイアウト Block_layout の定義がある。

__NSGlobalBlock__

キャプチャする情報がないブロックは、プログラムの一部としてコンパイルされ、動的なメモリを消費しない。このときブロックオブジェクトはオブジェクトではあるが(メッセージを受け取ることはできる)、実体は一つである。
globalスコープに置いた場合だけでなく、ブロックを関数内で宣言しても、キャプチャする情報がなければこの型になる。

__NSStackBlock__

キャプチャする情報があるとき、ブロックオブジェクトは __NSStackBlock__ として作られるようである。
その場でブロックを定義して呼び出すだけのときは、ブロックオブジェクトのライフサイクルは関数のスコープで終了し、解放される。
コールバック関数のようなケースでは、ブロックをretainしておく必要がある(普通はブロックを受け取る側が行う。ARC環境下では強参照で保持)。 __NSStackBlock__ クラスのオブジェクトをretainしようとすると、 __NSMallocBlock__ クラスに変換(コピー)されてからretainされるようになっている。

__NSMallocBlock__

ヒープ上に置かれたブロックオブジェクトである。
retainされることがわかっているなら、呼び出す時に最初から __NSMallocBlock__ で作る手段があってもよいような気がするが、試した限りでは常に __NSStackBlock__ として作られるようである。

tagged pointer

id に中身も入っている場合がある。このときオブジェクトの実体は id なので、 id がスタックにあればオブジェクトはスタック上にあることになる。

参考情報

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0