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

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

}

對(duì)應(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 };

會(huì)發(fā)現(xiàn)?__foo_block_impl_0 雖然在?__foo_block_desc_0 結(jié)構(gòu)體定義,但是在?__foo_block_impl_0 復(fù)制給Desc 時(shí)候并沒有明顯的發(fā)現(xiàn)調(diào)用__foo_block_impl_0拷貝的痕跡和屎,開始以為在調(diào)用block 靜態(tài)函數(shù)__foo_block_func_0 時(shí)候給int值變量復(fù)制系統(tǒng)會(huì)自動(dò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 屬于代碼段字符串符號(hào)表定義表達(dá)式(.quad随常,具體自行網(wǎng)上搜索)__copy_helper_block_e8_32s 潜沦。 其他地方實(shí)在無法聯(lián)系到調(diào)用___copy_helper_block_e8_32s進(jìn)行拷貝。

????.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)體值時(shí)發(fā)生了參數(shù)拷貝绪氛,本人對(duì)C++不是很熟悉唆鸡,不是很了解到底C++內(nèi)部是如何傳調(diào)用copy函數(shù),只能通過匯編跳轉(zhuǎn)猜測(cè)應(yīng)該是在block 內(nèi)部賦值DESC 時(shí)候進(jìn)行拷貝(可以當(dāng)參考思路不能當(dāng)正確答案钞楼,不敢胡亂猜測(cè) !-_-!)喇闸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市询件,隨后出現(xiàn)的幾起案子燃乍,更是在濱河造成了極大的恐慌,老刑警劉巖宛琅,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刻蟹,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘿辟,警方通過查閱死者的電腦和手機(jī)舆瘪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來红伦,“玉大人英古,你說我怎么就攤上這事£级粒” “怎么了召调?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我唠叛,道長只嚣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任艺沼,我火速辦了婚禮册舞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘障般。我一直安慰自己调鲸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布挽荡。 她就那樣靜靜地躺著线得,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徐伐。 梳的紋絲不亂的頭發(fā)上贯钩,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音办素,去河邊找鬼角雷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛性穿,可吹牛的內(nèi)容都是我干的勺三。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼需曾,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼吗坚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呆万,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤商源,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谋减,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牡彻,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年出爹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了庄吼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡严就,死狀恐怖总寻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梢为,我是刑警寧澤渐行,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布技矮,位于F島的核電站,受9級(jí)特大地震影響殊轴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜袒炉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一旁理、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧我磁,春花似錦孽文、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至郁副,卻和暖如春减牺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背存谎。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工拔疚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人既荚。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓稚失,卻偏偏與公主長得像,于是被迫代替她去往敵國和親恰聘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子句各,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容