block 捕获外部变量,内部调用copy 函数的时机

文章由来: ?重新看objc 编译成C++ 时候block 实现时梳理代码时候发现,C++实现的block 内部没找到直接调用__foo_block_impl_0* 这个函数(foo 是定义和实现block 的函数名称,具体看各自测试代block码在哪个函数里面调用的)。

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;

}

对应的C++ 编译之后的主要代码,其他多余代码已经去掉

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 };

会发现?__foo_block_impl_0 虽然在?__foo_block_desc_0 结构体定义,但是在?__foo_block_impl_0 复制给Desc 时候并没有明显的发现调用__foo_block_impl_0拷贝的痕迹,开始以为在调用block 静态函数__foo_block_func_0 时候给int值变量复制系统会自动调用__foo_block_impl_0之类的,但是后面发现并没有,于是 编译成汇编代码:我们把注意力集中到_foo 函数里面的?___block_descriptor_44_e8_32s_e5_v8 ,最终调用到 section里面去了,然后在里面执行了___copy_helper_block_e8_32s, 全局搜索下___copy_helper_block_e8_32s 发现 .section????__TEXT,__cstring,cstring_literals 属于代码段字符串符号表定义表达式(.quad,具体自行网上搜索)__copy_helper_block_e8_32s 。 其他地方实在无法联系到调用___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

目前大概明白了通过传结构体值时发生了参数拷贝,本人对C++不是很熟悉,不是很了解到底C++内部是如何传调用copy函数,只能通过汇编跳转猜测应该是在block 内部赋值DESC 时候进行拷贝(可以当参考思路不能当正确答案,不敢胡乱猜测 !-_-!)。

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容