block 捕獲外部變量,內(nèi)部調(diào)用copy 函數(shù)的時機

文章由來: ?重新看objc 編譯成C++ 時候block 實現(xiàn)時梳理代碼時候發(fā)現(xiàn),C++實現(xiàn)的block 內(nèi)部沒找到直接調(diào)用__foo_block_impl_0* 這個函數(shù)(foo 是定義和實現(xiàn)block 的函數(shù)名稱,具體看各自測試代block碼在哪個函數(shù)里面調(diào)用的)。

object 代碼

// main.m

#import <Foundation/Foundation.h>

void foo() {

????int a_int = 0;

????NSNumber *a_number = [NSNumber numberWithInt:0];

????void(^blockA)(void) = ^(void) {

????????NSLog(@"a_int = %d", a_int);

????????NSLog(@"a_number = %@", a_number);

????};

????a_int = 1;

????a_number = @1;

????blockA();

????return ;

}

int main(int argc, const char * argv[]) {

????foo();

????return 0;

}

對應(yīng)的C++ 編譯之后的主要代碼,其他多余代碼已經(jīng)去掉

struct __foo_block_impl_0 {

??struct __block_impl impl;

??struct __foo_block_desc_0* Desc;

??int a_int;

??NSNumber *a_number;

??__foo_block_impl_0(void *fp, struct __foo_block_desc_0 *desc, int _a_int, NSNumber *_a_number, int flags=0) : a_int(_a_int), a_number(_a_number) {

????impl.isa = &_NSConcreteStackBlock;

????impl.Flags = flags;

????impl.FuncPtr = fp;

????Desc = desc;

??}

};

static void __foo_block_func_0(struct __foo_block_impl_0 *__cself) {

??int a_int = __cself->a_int; // bound by copy

??NSNumber *a_number = __cself->a_number; // bound by copy

????????NSLog((NSString *)&__NSConstantStringImpl__var_folders_hf_ff518dhs4cq81s4jf93ppmg00000gn_T_blockTest_e6692f_mi_0, a_int);

????????NSLog((NSString *)&__NSConstantStringImpl__var_folders_hf_ff518dhs4cq81s4jf93ppmg00000gn_T_blockTest_e6692f_mi_1, a_number);

????}

static void __foo_block_copy_0(struct __foo_block_impl_0*dst, struct __foo_block_impl_0*src) {_Block_object_assign((void*)&dst->a_number, (void*)src->a_number, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __foo_block_dispose_0(struct __foo_block_impl_0*src) {_Block_object_dispose((void*)src->a_number, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __foo_block_desc_0 {

??size_t reserved;

??size_t Block_size;

??void (*copy)(struct __foo_block_impl_0*, struct __foo_block_impl_0*);

??void (*dispose)(struct __foo_block_impl_0*);

} __foo_block_desc_0_DATA = { 0, sizeof(struct __foo_block_impl_0), __foo_block_copy_0, __foo_block_dispose_0};

void foo() {

????int a_int = 0;

????NSNumber *a_number = ((NSNumber * _Nonnull (*)(id, SEL, int))(void *)objc_msgSend)((id)objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), 0);

????void(*blockA)(void) = ((void (*)())&__foo_block_impl_0((void *)__foo_block_func_0, &__foo_block_desc_0_DATA, a_int, a_number, 570425344));

????a_int = 1;

????a_number = ((NSNumber *(*)(Class, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), 1);

????((void (*)(__block_impl *))((__block_impl *)blockA)->FuncPtr)((__block_impl *)blockA);

????return ;

}

int main(int argc, const char * argv[]) {

????foo();

????return 0;

}

static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

會發(fā)現(xiàn)?__foo_block_impl_0 雖然在?__foo_block_desc_0 結(jié)構(gòu)體定義,但是在?__foo_block_impl_0 復(fù)制給Desc 時候并沒有明顯的發(fā)現(xiàn)調(diào)用__foo_block_impl_0拷貝的痕跡,開始以為在調(diào)用block 靜態(tài)函數(shù)__foo_block_func_0 時候給int值變量復(fù)制系統(tǒng)會自動調(diào)用__foo_block_impl_0之類的,但是后面發(fā)現(xiàn)并沒有,于是 編譯成匯編代碼:我們把注意力集中到_foo 函數(shù)里面的?___block_descriptor_44_e8_32s_e5_v8 ,最終調(diào)用到 section里面去了,然后在里面執(zhí)行了___copy_helper_block_e8_32s, 全局搜索下___copy_helper_block_e8_32s 發(fā)現(xiàn) .section????__TEXT,__cstring,cstring_literals 屬于代碼段字符串符號表定義表達式(.quad,具體自行網(wǎng)上搜索)__copy_helper_block_e8_32s 。 其他地方實在無法聯(lián)系到調(diào)用___copy_helper_block_e8_32s進行拷貝。

????.section????__TEXT,__text,regular,pure_instructions

????.build_version macos, 11, 0????sdk_version 12, 0

????.globl????_foo????????????????????????????## -- Begin function foo

????.p2align????4, 0x90

_foo:???????????????????????????????????## @foo

????.cfi_startproc

## %bb.0:

????pushq????%rbp

????.cfi_def_cfa_offset 16

????.cfi_offset %rbp, -16

????movq????%rsp, %rbp

????.cfi_def_cfa_register %rbp

????subq????$80, %rsp

????xorl????%edx, %edx

????movl????$0, -4(%rbp)

????movq????_OBJC_CLASSLIST_REFERENCES_$_(%rip), %rdi

????movq????_OBJC_SELECTOR_REFERENCES_(%rip), %rsi

????callq????*_objc_msgSend@GOTPCREL(%rip)

????movq????%rax, %rdi

????callq????_objc_retainAutoreleasedReturnValue

????movq????%rax, %rsi

????leaq????"___block_descriptor_44_e8_32s_e5_v8?0l"(%rip), %rax

????leaq????___foo_block_invoke(%rip), %rcx

????movq????__NSConcreteStackBlock@GOTPCREL(%rip), %rdx

????movq????%rsi, -16(%rbp)

????movq????%rdx, -72(%rbp)

????movl????$-1040187392, -64(%rbp)?????????## imm = 0xC2000000

????movl????$0, -60(%rbp)

????movq????%rcx, -56(%rbp)

????movq????%rax, -48(%rbp)

????movl????-4(%rbp), %eax

????movl????%eax, -32(%rbp)

????leaq????-72(%rbp), %rax

????addq????$32, %rax

????movq????%rax, -80(%rbp)?????????????????## 8-byte Spill

????movq????-16(%rbp), %rdi

????callq????*_objc_retain@GOTPCREL(%rip)

????movq????%rax, -40(%rbp)

????leaq????-72(%rbp), %rdi

????callq????_objc_retainBlock

????leaq????l__unnamed_nsconstantintegernumber_(%rip), %rsi

????movq????%rax, -24(%rbp)

????movl????$1, -4(%rbp)

????leaq????-16(%rbp), %rdi

????callq????_objc_storeStrong

????movq????-24(%rbp), %rax

????movq????%rax, %rdi

????callq????*16(%rax)

????xorl????%eax, %eax

????movl????%eax, %esi

????leaq????-24(%rbp), %rdi

????callq????_objc_storeStrong

????movq????-80(%rbp), %rdi?????????????????## 8-byte Reload

????xorl????%eax, %eax

????movl????%eax, %esi

????callq????_objc_storeStrong

????xorl????%eax, %eax

????movl????%eax, %esi

????leaq????-16(%rbp), %rdi

????callq????_objc_storeStrong

????addq????$80, %rsp

????popq????%rbp

????retq

????.cfi_endproc

????????????????????????????????????????## -- End function

????.p2align????4, 0x90????????????????????????## -- Begin function __foo_block_invoke

___foo_block_invoke:????????????????????## @__foo_block_invoke

????.cfi_startproc

## %bb.0:

????pushq????%rbp

????.cfi_def_cfa_offset 16

????.cfi_offset %rbp, -16

????movq????%rsp, %rbp

????.cfi_def_cfa_register %rbp

????subq????$32, %rsp

????movq????%rdi, %rax

????movq????%rax, -24(%rbp)?????????????????## 8-byte Spill

????leaq????L__unnamed_cfstring_(%rip), %rdi

????movq????%rax, -8(%rbp)

????movq????%rax, %rcx

????movq????%rcx, -16(%rbp)

????movl????40(%rax), %esi

????movb????$0, %al

????callq????_NSLog

????movq????-24(%rbp), %rax?????????????????## 8-byte Reload

????leaq????L__unnamed_cfstring_.2(%rip), %rdi

????movq????32(%rax), %rsi

????movb????$0, %al

????callq????_NSLog

????addq????$32, %rsp

????popq????%rbp

????retq

????.cfi_endproc

????????????????????????????????????????## -- End function

????.private_extern????___copy_helper_block_e8_32s ## -- Begin function __copy_helper_block_e8_32s

????.globl????___copy_helper_block_e8_32s

????.weak_def_can_be_hidden????___copy_helper_block_e8_32s

????.p2align????4, 0x90

___copy_helper_block_e8_32s:????????????## @__copy_helper_block_e8_32s

????.cfi_startproc

## %bb.0:

????pushq????%rbp

????.cfi_def_cfa_offset 16

????.cfi_offset %rbp, -16

????movq????%rsp, %rbp

????.cfi_def_cfa_register %rbp

????subq????$16, %rsp

????movq????%rdi, -8(%rbp)

????movq????%rsi, -16(%rbp)

????movq????-16(%rbp), %rcx

????movq????-8(%rbp), %rax

????movq????%rax, %rdi

????addq????$32, %rdi

????movq????32(%rcx), %rsi

????movq????$0, 32(%rax)

????callq????_objc_storeStrong

????addq????$16, %rsp

????popq????%rbp

????retq

????.cfi_endproc

????????????????????????????????????????## -- End function

????.private_extern????___destroy_helper_block_e8_32s ## -- Begin function __destroy_helper_block_e8_32s

????.globl????___destroy_helper_block_e8_32s

????.weak_def_can_be_hidden????___destroy_helper_block_e8_32s

????.p2align????4, 0x90

___destroy_helper_block_e8_32s:?????????## @__destroy_helper_block_e8_32s

????.cfi_startproc

## %bb.0:

????pushq????%rbp

????.cfi_def_cfa_offset 16

????.cfi_offset %rbp, -16

????movq????%rsp, %rbp

????.cfi_def_cfa_register %rbp

????subq????$16, %rsp

????xorl????%eax, %eax

????movl????%eax, %esi

????movq????%rdi, -8(%rbp)

????movq????-8(%rbp), %rdi

????addq????$32, %rdi

????callq????_objc_storeStrong

????addq????$16, %rsp

????popq????%rbp

????retq

????.cfi_endproc

????????????????????????????????????????## -- End function

????.globl????_main???????????????????????????## -- Begin function main

????.p2align????4, 0x90

_main:??????????????????????????????????## @main

????.cfi_startproc

## %bb.0:

????pushq????%rbp

????.cfi_def_cfa_offset 16

????.cfi_offset %rbp, -16

????movq????%rsp, %rbp

????.cfi_def_cfa_register %rbp

????subq????$16, %rsp

????movl????$0, -4(%rbp)

????movl????%edi, -8(%rbp)

????movq????%rsi, -16(%rbp)

????callq????_foo

????xorl????%eax, %eax

????addq????$16, %rsp

????popq????%rbp

????retq

????.cfi_endproc

????????????????????????????????????????## -- End function

????.section????__DATA,__objc_classrefs,regular,no_dead_strip

????.p2align????3??????????????????????????????## @"OBJC_CLASSLIST_REFERENCES_$_"

_OBJC_CLASSLIST_REFERENCES_$_:

????.quad????_OBJC_CLASS_$_NSNumber

????.section????__TEXT,__objc_methname,cstring_literals

L_OBJC_METH_VAR_NAME_:??????????????????## @OBJC_METH_VAR_NAME_

????.asciz????"numberWithInt:"

????.section????__DATA,__objc_selrefs,literal_pointers,no_dead_strip

????.p2align????3??????????????????????????????## @OBJC_SELECTOR_REFERENCES_

_OBJC_SELECTOR_REFERENCES_:

????.quad????L_OBJC_METH_VAR_NAME_

????.section????__TEXT,__cstring,cstring_literals

L_.str:?????????????????????????????????## @.str

????.asciz????"a_int = %d"

????.section????__DATA,__cfstring

????.p2align????3??????????????????????????????## @_unnamed_cfstring_

L__unnamed_cfstring_:

????.quad????___CFConstantStringClassReference

????.long????1992????????????????????????????## 0x7c8

????.space????4

????.quad????L_.str

????.quad????10??????????????????????????????## 0xa

????.section????__TEXT,__cstring,cstring_literals

L_.str.1:???????????????????????????????## @.str.1

????.asciz????"a_number = %@"

????.section????__DATA,__cfstring

????.p2align????3??????????????????????????????## @_unnamed_cfstring_.2

L__unnamed_cfstring_.2:

????.quad????___CFConstantStringClassReference

????.long????1992????????????????????????????## 0x7c8

????.space????4

????.quad????L_.str.1

????.quad????13??????????????????????????????## 0xd

????.section????__TEXT,__cstring,cstring_literals

L_.str.3:???????????????????????????????## @.str.3

????.asciz????"v8@?0"

????.private_extern????"___block_descriptor_44_e8_32s_e5_v8?0l" ## @"__block_descriptor_44_e8_32s_e5_v8\01?0l"

????.section????__DATA,__const

????.globl????"___block_descriptor_44_e8_32s_e5_v8?0l"

????.weak_def_can_be_hidden????"___block_descriptor_44_e8_32s_e5_v8?0l"

????.p2align????3

"___block_descriptor_44_e8_32s_e5_v8?0l":

????.quad????0??????????????????????????????## 0x0

????.quad????44??????????????????????????????## 0x2c

????.quad????___copy_helper_block_e8_32s

????.quad????___destroy_helper_block_e8_32s

????.quad????L_.str.3

????.quad????256????????????????????????????## 0x100

????.section????__TEXT,__cstring,cstring_literals

L_.str.4:???????????????????????????????## @.str.4

????.asciz????"i"

????.section????__DATA,__objc_intobj,regular,no_dead_strip

????.p2align????3??????????????????????????????## @_unnamed_nsconstantintegernumber_

l__unnamed_nsconstantintegernumber_:

????.quad????_OBJC_CLASS_$_NSConstantIntegerNumber

????.quad????L_.str.4

????.quad????1??????????????????????????????## 0x1

????.section????__DATA,__objc_imageinfo,regular,no_dead_strip

L_OBJC_IMAGE_INFO:

????.long????0

????.long????64

.subsections_via_symbols

目前大概明白了通過傳結(jié)構(gòu)體值時發(fā)生了參數(shù)拷貝,本人對C++不是很熟悉,不是很了解到底C++內(nèi)部是如何傳調(diào)用copy函數(shù),只能通過匯編跳轉(zhuǎn)猜測應(yīng)該是在block 內(nèi)部賦值DESC 時候進行拷貝(可以當(dāng)參考思路不能當(dāng)正確答案,不敢胡亂猜測 !-_-!)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容