答えて
内readonly copy
なり、答えはYesです。
外部ブロックは非同期にディスパッチされ、ランタイムはこのブロックのヒープ上にコピーを作成します。下に示すように、Block Implementation Specification - Clang 3.4 Documentationに記述されているように、内部ブロックのインポートされた変数もヒープにコピーされます。
OPの例では、「ブロック参照のインポートされたconstコピー」があります。
私は仕様の例を使用しています:
void (^existingBlock)(void) = ...;
void (^vv)(void) = ^{ existingBlock(); }
vv();
仕様はcopy_helper
とdispose_helper
機能が必要とされていると述べている:
copy_helper機能は、両方の既存のスタックベースのポインタを渡されます新しいヒープ・バージョンへのポインタを返し、ランタイムにコールバックして、ブロック内のインポートされたフィールドに対して実際にコピー操作を実行する必要があります。
仕様の次のコード例は、解読が難しい(実際には、外側のブロックがヒープにコピーされたときに何が起こるかについて実際には不足しています)。とにかく、内部ブロックのインポートされた変数が(再帰的に)外部ブロックの生の記憶域にコピーされることを仕様が示しているように見えます。
ヒープ上に外部ブロックがコピーされると、内部ブロックのインポートされた変数が最終的にヒープ上にも存在するように見えます。
これは直感的に意味があります。
私はこれを実証する小さなテストプログラムを作った: (あなたはデバッグし、表面の下で何が起こっているか把握するために分解を調べなければならない)。(ローカルおよびインポート変数のアドレスによって示されるように)ブロックは、メインスレッド上で実行される
Stack: &x: 0x7fff5fbff868
Stack: &x: 0x7fff5fbff864
------- on main thread -------
&y0: 0x7fff5fbff70c
&y1: 0x7fff5fbff708
&x0: 0x1001081e0
&x1: 0x1001081e4
&y2: 0x7fff5fbff76c
&y3: 0x7fff5fbff768
&x0: 0x10010a588
&x1: 0x10010a58c
------- on thread 2 -------
&y0: 0x1000e5d9c
&y1: 0x1000e5d98
&x0: 0x1001081e0
&x1: 0x1001081e4
&y2: 0x1000e5dfc
&y3: 0x1000e5df8
&x0: 0x10010a588
&x1: 0x10010a58c
&y4: 0x1000e5e6c
&y5: 0x1000e5e68
&x0: 0x10010a5e8
&x1: 0x10010a5ec
は、それがスタックに住んで次のよう
#import <Foundation/Foundation.h>
void foo(int param)
{
int x0 = param;
int x1 = param + 1;
void (^existingBlock)(void) = ^{
int y0 = x0;
int y1 = x1;
printf("&y0: %p\n", &y0);
printf("&y1: %p\n", &y1);
printf("&x0: %p\n", &x0);
printf("&x1: %p\n", &x1);
};
void (^vv)(void) = ^{
int y2 = x0;
int y3 = x1;
existingBlock();
printf("&y2: %p\n", &y2);
printf("&y3: %p\n", &y3);
printf("&x0: %p\n", &x0);
printf("&x1: %p\n", &x1);
};
printf("Stack: &x: %p\n", &x0);
printf("Stack: &x: %p\n", &x1);
printf("------- on main thread -------\n");
vv();
dispatch_async(dispatch_get_global_queue(0, 0), ^{
printf("------- on thread 2 -------\n");
assert(vv);
sleep(1);
int y4 = x0;
int y5 = x1;
vv();
printf("&y4: %p\n", &y4);
printf("&y5: %p\n", &y5);
printf("&x0: %p\n", &x0);
printf("&x1: %p\n", &x1);
});
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
foo(1);
sleep(2);
}
return 0;
}
出力されます。 dispatch_async
によって実行されると、ランタイムはブロックのローカル変数とインポートされた変数のアドレスからわかるように、内部ブロックを含むブロックをコピーしました。
ブロックvv
をヒープにコピーするために、copy_helper_block
関数でブレークポイントを設定することができます。
block
は、普通のオブジェクトと同じように別のブロックにキャッチされているため、ed(1セクタごとにコピーされません)です。async_block
ブロックのコピーは、ブロックオブジェクトを送信した結果、ブロックをコピーしたオーバーライドretain
メソッドを呼び出した[block retain]
メッセージです。 Apple docsdispatch_async
上から
:だから
ブロック
The block to submit to the target dispatch queue. This function performs Block_copy and Block_release on behalf of callers. This parameter cannot be NULL.
は、async_block
がコピーされます。
、block
(あなたの例ではasync_block
の内側)、私は信じてasync_block
- 1. は以下を考えるとScalaの
- 2. XCTAssertEqualは以下スウィフトクラスを考えるスウィフト
- 3. sqlite、外部キー参照をカウントする
- 4. ブロック内の弱い参照
- 5. 内部クラス参照は
- 6. は、以下の指標を考えるalgolia
- 7. protobufの内部参照?
- 8. 内部インデックスへの参照?
- 9. 無名ブロック内のカーソルの参照
- 10. 弱ブロック内の参照およびサイクル
- 11. のMongoDB:私は以下のコレクションを持っている参照
- 12. 以下の形式(一例)のアレイを考えるnumpyの
- 13. @synchronizedブロック対GCD dispatch_async()
- 14. 同期ブロックとdispatch_async
- 15. エルム - 以下の仮定の機能を考える要素
- 16. JSON内部参照宣言
- 17. Android:以下の状況でHTML内のCSSファイルを参照する方法
- 18. トラブルそれ以下のSQLを考える
- 19. を渡すのstd ::以下prerequisits考えるとC++
- 20. のSQLServer 2008 - ストアドプロシージャの戻り値例外以下SP考える
- 21. - データ以下の考える新しい列に列のエントリ
- 22. ベクトル::この定義を考えると、参照
- 23. Javaのリスト内の内部クラスを参照するには
- 24. iOS自動参照カウント(ARC)の下位互換性?
- 25. 参照オブジェクトに指摘し、次を考える
- 26. C++変換constが参照渡しテンプレートを考える
- 27. 私は以下を参照してWebサービス
- 28. String.Substring():コピーまたは参照?
- 29. コンストラクタ内部のこの参照
- 30. コールセッタークラスの任意のプロパティには、以下のようなクラスを考える
この情報はどこから入手しましたか?ブロックを保持すると何ができますか? –
ブロックは 'NSObject'から継承しています(両方ともAppleの_NSBlock'クラスとGNUstep'GSBlock'クラスの両方ですが、どちらもプライベートですが、例外として、Core-Coundationに似たCベースのアプローチを採用しています)あなたのNSArrayとNSStringのように別のブロックで捕まえられたときに 'objc_retain()' edを取得しました –
@Gabriele Petronella iOS 6.0とMac OS X 10.8以来、Maxthonはブロックが "Objects"であると言っても間違いありません。 ARCはそれらをオブジェクトオブジェクトポインタとして管理します。しかし、ブロックは自動的にコピーされます。この例では、Mac OS X 10.8またはiOS 6とARCが有効な場合でも、ヒープにシフトするために、ブロック 'ブロック 'を明示的にコピーする必要があります。さもなければ、 'block'がスタックに残り、非同期に呼び出されたブロック' async_block'がクラッシュします。 – CouchDeveloper